~x2go/x2go/pinentry-x2go_master

« back to all changes in this revision

Viewing changes to gtk/gtksecentry.c

  • Committer: Mike Gabriel
  • Date: 2012-06-13 12:55:37 UTC
  • Revision ID: git-v1:d2060291d5cc7beb92f78168e48ececfe765d552
Strip code project down to its essentials, remove a lot of unneeded cruft. / Make code tree fully build with autotools, see README file for further info.

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 and Josh MacDonald
3
 
 *
4
 
 * This library is free software; you can redistribute it and/or
5
 
 * modify it under the terms of the GNU Library General Public
6
 
 * License as published by the Free Software Foundation; either
7
 
 * version 2 of the License, or (at your option) any later version.
8
 
 *
9
 
 * This library is distributed in the hope that it will be useful,
10
 
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11
 
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12
 
 * Library General Public License for more details.
13
 
 *
14
 
 * You should have received a copy of the GNU Library General Public
15
 
 * License along with this library; if not, write to the
16
 
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17
 
 * Boston, MA 02111-1307, USA.
18
 
 */
19
 
 
20
 
/*
21
 
 * Modified by the GTK+ Team and others 1997-1999.  See the AUTHORS
22
 
 * file for a list of people on the GTK+ Team.  See the ChangeLog
23
 
 * files for a list of changes.  These files are distributed with
24
 
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
25
 
 */
26
 
 
27
 
/*
28
 
 * Further modified by robbe to form GtkSecureEntry
29
 
 *
30
 
 * Notes:
31
 
 * text: classified
32
 
 * text_length: unclassified, can be seen on the screen (should that change??)
33
 
 * char_offsets: unclassified, because it only gives the stars' offsets
34
 
 *              (which makes it pretty pointless, anyway)
35
 
 * text_mb: classified (essentially the same as text)
36
 
 *
37
 
 */
38
 
 
39
 
#include <ctype.h>
40
 
#include <string.h>
41
 
#include <gdk/gdkkeysyms.h>
42
 
#include <gdk/gdki18n.h>
43
 
#include <gtk/gtkmain.h>
44
 
#include <gtk/gtkselection.h>
45
 
#include <gtk/gtksignal.h>
46
 
#include <gtk/gtkstyle.h>
47
 
#include "gtksecentry.h"
48
 
#include "memory.h"
49
 
 
50
 
#define MIN_SECURE_ENTRY_WIDTH  150
51
 
#define DRAW_TIMEOUT     20
52
 
#define INNER_BORDER     2
53
 
 
54
 
enum {
55
 
  ARG_0,
56
 
  ARG_MAX_LENGTH,
57
 
  ARG_VISIBILITY
58
 
};
59
 
 
60
 
 
61
 
static void gtk_secure_entry_class_init          (GtkSecureEntryClass     *klass);
62
 
static void gtk_secure_entry_init                (GtkSecureEntry          *entry);
63
 
static void gtk_secure_entry_set_arg              (GtkObject         *object,
64
 
                                           GtkArg            *arg,
65
 
                                           guint              arg_id);
66
 
static void gtk_secure_entry_get_arg              (GtkObject         *object,
67
 
                                           GtkArg            *arg,
68
 
                                           guint              arg_id);
69
 
static void gtk_secure_entry_finalize            (GtkObject         *object);
70
 
static void gtk_secure_entry_realize             (GtkWidget         *widget);
71
 
static void gtk_secure_entry_unrealize           (GtkWidget         *widget);
72
 
static void gtk_secure_entry_draw_focus          (GtkWidget         *widget);
73
 
static void gtk_secure_entry_size_request        (GtkWidget         *widget,
74
 
                                           GtkRequisition    *requisition);
75
 
static void gtk_secure_entry_size_allocate       (GtkWidget         *widget,
76
 
                                           GtkAllocation     *allocation);
77
 
static void gtk_secure_entry_make_backing_pixmap (GtkSecureEntry *entry,
78
 
                                           gint width, gint height);
79
 
static void gtk_secure_entry_draw                (GtkWidget         *widget,
80
 
                                           GdkRectangle      *area);
81
 
static gint gtk_secure_entry_expose              (GtkWidget         *widget,
82
 
                                           GdkEventExpose    *event);
83
 
static gint gtk_secure_entry_button_press        (GtkWidget         *widget,
84
 
                                           GdkEventButton    *event);
85
 
static gint gtk_secure_entry_button_release      (GtkWidget         *widget,
86
 
                                           GdkEventButton    *event);
87
 
static gint gtk_secure_entry_motion_notify       (GtkWidget         *widget,
88
 
                                           GdkEventMotion    *event);
89
 
static gint gtk_secure_entry_key_press           (GtkWidget         *widget,
90
 
                                           GdkEventKey       *event);
91
 
static gint gtk_secure_entry_focus_in            (GtkWidget         *widget,
92
 
                                           GdkEventFocus     *event);
93
 
static gint gtk_secure_entry_focus_out           (GtkWidget         *widget,
94
 
                                           GdkEventFocus     *event);
95
 
static void gtk_secure_entry_draw_text           (GtkSecureEntry          *entry);
96
 
static void gtk_secure_entry_draw_cursor         (GtkSecureEntry          *entry);
97
 
static void gtk_secure_entry_draw_cursor_on_drawable
98
 
                                          (GtkSecureEntry          *entry,
99
 
                                           GdkDrawable       *drawable);
100
 
static void gtk_secure_entry_style_set            (GtkWidget         *widget,
101
 
                                           GtkStyle          *previous_style);
102
 
static void gtk_secure_entry_state_changed        (GtkWidget         *widget,
103
 
                                           GtkStateType       previous_state);
104
 
#ifdef USE_XIM
105
 
static void gtk_secure_entry_update_ic_attr      (GtkWidget         *widget);
106
 
#endif
107
 
static void gtk_secure_entry_queue_draw          (GtkSecureEntry          *entry);
108
 
static gint gtk_secure_entry_timer               (gpointer           data);
109
 
static gint gtk_secure_entry_position            (GtkSecureEntry          *entry,
110
 
                                           gint               x);
111
 
static void entry_adjust_scroll           (GtkSecureEntry          *entry);
112
 
static void gtk_secure_entry_grow_text           (GtkSecureEntry          *entry);
113
 
static void gtk_secure_entry_insert_text         (GtkEditable       *editable,
114
 
                                           const gchar       *new_text,
115
 
                                           gint               new_text_length,
116
 
                                           gint              *position);
117
 
static void gtk_secure_entry_delete_text         (GtkEditable       *editable,
118
 
                                           gint               start_pos,
119
 
                                           gint               end_pos);
120
 
static void gtk_secure_entry_update_text         (GtkEditable       *editable,
121
 
                                           gint               start_pos,
122
 
                                           gint               end_pos);
123
 
static gchar *gtk_secure_entry_get_chars         (GtkEditable       *editable,
124
 
                                           gint               start_pos,
125
 
                                           gint               end_pos);
126
 
 
127
 
/* Binding actions */
128
 
static void gtk_secure_entry_move_cursor         (GtkEditable *editable,
129
 
                                           gint         x,
130
 
                                           gint         y);
131
 
static void gtk_secure_entry_move_word           (GtkEditable *editable,
132
 
                                           gint         n);
133
 
static void gtk_secure_entry_move_to_column      (GtkEditable *editable,
134
 
                                           gint         row);
135
 
static void gtk_secure_entry_kill_char           (GtkEditable *editable,
136
 
                                           gint         direction);
137
 
static void gtk_secure_entry_kill_word           (GtkEditable *editable,
138
 
                                           gint         direction);
139
 
static void gtk_secure_entry_kill_line           (GtkEditable *editable,
140
 
                                           gint         direction);
141
 
 
142
 
/* To be removed */
143
 
static void gtk_move_forward_character    (GtkSecureEntry          *entry);
144
 
static void gtk_move_backward_character   (GtkSecureEntry          *entry);
145
 
static void gtk_move_forward_word         (GtkSecureEntry          *entry);
146
 
static void gtk_move_backward_word        (GtkSecureEntry          *entry);
147
 
static void gtk_move_beginning_of_line    (GtkSecureEntry          *entry);
148
 
static void gtk_move_end_of_line          (GtkSecureEntry          *entry);
149
 
static void gtk_delete_forward_character  (GtkSecureEntry          *entry);
150
 
static void gtk_delete_backward_character (GtkSecureEntry          *entry);
151
 
static void gtk_delete_forward_word       (GtkSecureEntry          *entry);
152
 
static void gtk_delete_backward_word      (GtkSecureEntry          *entry);
153
 
static void gtk_delete_line               (GtkSecureEntry          *entry);
154
 
static void gtk_delete_to_line_end        (GtkSecureEntry          *entry);
155
 
static void gtk_select_word               (GtkSecureEntry          *entry,
156
 
                                           guint32            time);
157
 
static void gtk_select_line               (GtkSecureEntry          *entry,
158
 
                                           guint32            time);
159
 
 
160
 
 
161
 
static void gtk_secure_entry_set_selection       (GtkEditable       *editable,
162
 
                                           gint               start,
163
 
                                           gint               end);
164
 
 
165
 
static void gtk_secure_entry_recompute_offsets   (GtkSecureEntry          *entry);
166
 
static gint gtk_secure_entry_find_position       (GtkSecureEntry          *entry, 
167
 
                                           gint               position);
168
 
static void gtk_secure_entry_set_position_from_editable (GtkEditable *editable,
169
 
                                                  gint         position);
170
 
 
171
 
static GtkWidgetClass *parent_class = NULL;
172
 
static GdkAtom ctext_atom = GDK_NONE;
173
 
 
174
 
static const GtkTextFunction control_keys[26] =
175
 
{
176
 
  (GtkTextFunction)gtk_move_beginning_of_line,    /* a */
177
 
  (GtkTextFunction)gtk_move_backward_character,   /* b */
178
 
  (GtkTextFunction)gtk_editable_copy_clipboard,   /* c */
179
 
  (GtkTextFunction)gtk_delete_forward_character,  /* d */
180
 
  (GtkTextFunction)gtk_move_end_of_line,          /* e */
181
 
  (GtkTextFunction)gtk_move_forward_character,    /* f */
182
 
  NULL,                                           /* g */
183
 
  (GtkTextFunction)gtk_delete_backward_character, /* h */
184
 
  NULL,                                           /* i */
185
 
  NULL,                                           /* j */
186
 
  (GtkTextFunction)gtk_delete_to_line_end,        /* k */
187
 
  NULL,                                           /* l */
188
 
  NULL,                                           /* m */
189
 
  NULL,                                           /* n */
190
 
  NULL,                                           /* o */
191
 
  NULL,                                           /* p */
192
 
  NULL,                                           /* q */
193
 
  NULL,                                           /* r */
194
 
  NULL,                                           /* s */
195
 
  NULL,                                           /* t */
196
 
  (GtkTextFunction)gtk_delete_line,               /* u */
197
 
  (GtkTextFunction)gtk_editable_paste_clipboard,  /* v */
198
 
  (GtkTextFunction)gtk_delete_backward_word,      /* w */
199
 
  (GtkTextFunction)gtk_editable_cut_clipboard,    /* x */
200
 
  NULL,                                           /* y */
201
 
  NULL,                                           /* z */
202
 
};
203
 
 
204
 
static const GtkTextFunction alt_keys[26] =
205
 
{
206
 
  NULL,                                           /* a */
207
 
  (GtkTextFunction)gtk_move_backward_word,        /* b */
208
 
  NULL,                                           /* c */
209
 
  (GtkTextFunction)gtk_delete_forward_word,       /* d */
210
 
  NULL,                                           /* e */
211
 
  (GtkTextFunction)gtk_move_forward_word,         /* f */
212
 
  NULL,                                           /* g */
213
 
  NULL,                                           /* h */
214
 
  NULL,                                           /* i */
215
 
  NULL,                                           /* j */
216
 
  NULL,                                           /* k */
217
 
  NULL,                                           /* l */
218
 
  NULL,                                           /* m */
219
 
  NULL,                                           /* n */
220
 
  NULL,                                           /* o */
221
 
  NULL,                                           /* p */
222
 
  NULL,                                           /* q */
223
 
  NULL,                                           /* r */
224
 
  NULL,                                           /* s */
225
 
  NULL,                                           /* t */
226
 
  NULL,                                           /* u */
227
 
  NULL,                                           /* v */
228
 
  NULL,                                           /* w */
229
 
  NULL,                                           /* x */
230
 
  NULL,                                           /* y */
231
 
  NULL,                                           /* z */
232
 
};
233
 
 
234
 
gboolean g_use_secure_mem = FALSE;
235
 
 
236
 
#  define g_sec_new(type, count)          \
237
 
      ((type *) g_sec_malloc ((unsigned) sizeof (type) * (count)))
238
 
 
239
 
#define WITH_SECURE_MEM(EXP)    do { \
240
 
                                        gboolean tmp = g_use_secure_mem; \
241
 
                                        g_use_secure_mem = TRUE; \
242
 
                                        EXP; \
243
 
                                        g_use_secure_mem = tmp; \
244
 
                                } while(0)
245
 
 
246
 
gpointer
247
 
g_malloc (gulong size)
248
 
{
249
 
  gpointer p;
250
 
  
251
 
  if (size == 0)
252
 
    return NULL;
253
 
 
254
 
  if (g_use_secure_mem)
255
 
    p = (gpointer) secmem_malloc(size);
256
 
  else
257
 
    p = (gpointer) malloc (size);
258
 
  if (!p)
259
 
    g_error ("could not allocate %ld bytes", size);
260
 
 
261
 
  return p;
262
 
}
263
 
 
264
 
gpointer
265
 
g_malloc0 (gulong size)
266
 
{
267
 
  gpointer p;
268
 
  
269
 
  if (size == 0)
270
 
    return NULL;
271
 
  
272
 
  if (g_use_secure_mem) {
273
 
    p = (gpointer) secmem_malloc(size);
274
 
    if (p)
275
 
      memset(p, 0, size);
276
 
  } else
277
 
    p = (gpointer) calloc (size, 1);
278
 
  if (!p)
279
 
    g_error ("could not allocate %ld bytes", size);
280
 
  
281
 
  return p;
282
 
}
283
 
 
284
 
gpointer
285
 
g_realloc (gpointer mem,
286
 
           gulong   size)
287
 
{
288
 
  gpointer p;
289
 
  
290
 
  if (size == 0)
291
 
    {
292
 
      g_free (mem);
293
 
    
294
 
      return NULL;
295
 
    }
296
 
  
297
 
  if (!mem)
298
 
    {
299
 
      if (g_use_secure_mem)
300
 
        p = (gpointer) secmem_malloc (size);
301
 
      else
302
 
        p = (gpointer) malloc (size);
303
 
    }
304
 
  else
305
 
    {
306
 
      if (g_use_secure_mem) {
307
 
        g_assert(m_is_secure(mem));
308
 
        p = (gpointer) secmem_realloc (mem, size);
309
 
      } else
310
 
        p = (gpointer) realloc (mem, size);
311
 
    }
312
 
  
313
 
  if (!p)
314
 
    g_error ("could not reallocate %lu bytes", (gulong) size);
315
 
  
316
 
  return p;
317
 
}
318
 
 
319
 
void
320
 
g_free (gpointer mem)
321
 
{
322
 
  if (mem)
323
 
    {
324
 
      if (m_is_secure(mem))
325
 
        secmem_free(mem);
326
 
      else
327
 
        free (mem);
328
 
    }
329
 
}
330
 
 
331
 
GtkType
332
 
gtk_secure_entry_get_type (void)
333
 
{
334
 
  static GtkType entry_type = 0;
335
 
 
336
 
  if (!entry_type)
337
 
    {
338
 
      static const GtkTypeInfo entry_info =
339
 
      {
340
 
        "GtkSecureEntry",
341
 
        sizeof (GtkSecureEntry),
342
 
        sizeof (GtkSecureEntryClass),
343
 
        (GtkClassInitFunc) gtk_secure_entry_class_init,
344
 
        (GtkObjectInitFunc) gtk_secure_entry_init,
345
 
        /* reserved_1 */ NULL,
346
 
        /* reserved_2 */ NULL,
347
 
        (GtkClassInitFunc) NULL,
348
 
      };
349
 
 
350
 
      entry_type = gtk_type_unique (GTK_TYPE_EDITABLE, &entry_info);
351
 
    }
352
 
 
353
 
  return entry_type;
354
 
}
355
 
 
356
 
static void
357
 
gtk_secure_entry_class_init (GtkSecureEntryClass *class)
358
 
{
359
 
  GtkObjectClass *object_class;
360
 
  GtkWidgetClass *widget_class;
361
 
  GtkEditableClass *editable_class;
362
 
 
363
 
  object_class = (GtkObjectClass*) class;
364
 
  widget_class = (GtkWidgetClass*) class;
365
 
  editable_class = (GtkEditableClass*) class;
366
 
  parent_class = gtk_type_class (GTK_TYPE_EDITABLE);
367
 
 
368
 
  gtk_object_add_arg_type ("GtkSecureEntry::max_length", GTK_TYPE_UINT, GTK_ARG_READWRITE, ARG_MAX_LENGTH);
369
 
  gtk_object_add_arg_type ("GtkSecureEntry::visibility", GTK_TYPE_BOOL, GTK_ARG_READWRITE, ARG_VISIBILITY);
370
 
 
371
 
  object_class->set_arg = gtk_secure_entry_set_arg;
372
 
  object_class->get_arg = gtk_secure_entry_get_arg;
373
 
  object_class->finalize = gtk_secure_entry_finalize;
374
 
 
375
 
  widget_class->realize = gtk_secure_entry_realize;
376
 
  widget_class->unrealize = gtk_secure_entry_unrealize;
377
 
  widget_class->draw_focus = gtk_secure_entry_draw_focus;
378
 
  widget_class->size_request = gtk_secure_entry_size_request;
379
 
  widget_class->size_allocate = gtk_secure_entry_size_allocate;
380
 
  widget_class->draw = gtk_secure_entry_draw;
381
 
  widget_class->expose_event = gtk_secure_entry_expose;
382
 
  widget_class->button_press_event = gtk_secure_entry_button_press;
383
 
  widget_class->button_release_event = gtk_secure_entry_button_release;
384
 
  widget_class->motion_notify_event = gtk_secure_entry_motion_notify;
385
 
  widget_class->key_press_event = gtk_secure_entry_key_press;
386
 
  widget_class->focus_in_event = gtk_secure_entry_focus_in;
387
 
  widget_class->focus_out_event = gtk_secure_entry_focus_out;
388
 
  widget_class->style_set = gtk_secure_entry_style_set;
389
 
  widget_class->state_changed = gtk_secure_entry_state_changed;
390
 
 
391
 
  editable_class->insert_text = gtk_secure_entry_insert_text;
392
 
  editable_class->delete_text = gtk_secure_entry_delete_text;
393
 
  editable_class->changed = (void (*)(GtkEditable *)) entry_adjust_scroll;
394
 
 
395
 
  editable_class->move_cursor = gtk_secure_entry_move_cursor;
396
 
  editable_class->move_word = gtk_secure_entry_move_word;
397
 
  editable_class->move_to_column = gtk_secure_entry_move_to_column;
398
 
 
399
 
  editable_class->kill_char = gtk_secure_entry_kill_char;
400
 
  editable_class->kill_word = gtk_secure_entry_kill_word;
401
 
  editable_class->kill_line = gtk_secure_entry_kill_line;
402
 
 
403
 
  editable_class->update_text = gtk_secure_entry_update_text;
404
 
  editable_class->get_chars   = gtk_secure_entry_get_chars;
405
 
  editable_class->set_selection = gtk_secure_entry_set_selection;
406
 
  editable_class->set_position = gtk_secure_entry_set_position_from_editable;
407
 
}
408
 
 
409
 
static void
410
 
gtk_secure_entry_set_arg (GtkObject      *object,
411
 
                   GtkArg         *arg,
412
 
                   guint           arg_id)
413
 
{
414
 
  GtkSecureEntry *entry;
415
 
 
416
 
  entry = GTK_SECURE_ENTRY (object);
417
 
 
418
 
  switch (arg_id)
419
 
    {
420
 
    case ARG_MAX_LENGTH:
421
 
      gtk_secure_entry_set_max_length (entry, GTK_VALUE_UINT (*arg));
422
 
      break;
423
 
    case ARG_VISIBILITY:
424
 
      gtk_secure_entry_set_visibility (entry, GTK_VALUE_BOOL (*arg));
425
 
      break;
426
 
    default:
427
 
      break;
428
 
    }
429
 
}
430
 
 
431
 
static void
432
 
gtk_secure_entry_get_arg (GtkObject      *object,
433
 
                   GtkArg         *arg,
434
 
                   guint           arg_id)
435
 
{
436
 
  GtkSecureEntry *entry;
437
 
 
438
 
  entry = GTK_SECURE_ENTRY (object);
439
 
 
440
 
  switch (arg_id)
441
 
    {
442
 
    case ARG_MAX_LENGTH:
443
 
      GTK_VALUE_UINT (*arg) = entry->text_max_length;
444
 
      break;
445
 
    case ARG_VISIBILITY:
446
 
      GTK_VALUE_BOOL (*arg) = GTK_EDITABLE (entry)->visible;
447
 
      break;
448
 
    default:
449
 
      arg->type = GTK_TYPE_INVALID;
450
 
      break;
451
 
    }
452
 
}
453
 
 
454
 
static void
455
 
gtk_secure_entry_init (GtkSecureEntry *entry)
456
 
{
457
 
  GTK_WIDGET_SET_FLAGS (entry, GTK_CAN_FOCUS);
458
 
 
459
 
  entry->text_area = NULL;
460
 
  entry->backing_pixmap = NULL;
461
 
  entry->text = NULL;
462
 
  entry->text_size = 0;
463
 
  entry->text_length = 0;
464
 
  entry->text_max_length = 0;
465
 
  entry->scroll_offset = 0;
466
 
  entry->timer = 0;
467
 
  entry->button = 0;
468
 
  entry->visible = 1;
469
 
 
470
 
  entry->char_offset = NULL;
471
 
  entry->text_mb = NULL;
472
 
  entry->text_mb_dirty = TRUE;
473
 
  entry->use_wchar = FALSE;
474
 
 
475
 
  gtk_secure_entry_grow_text (entry);
476
 
}
477
 
 
478
 
GtkWidget*
479
 
gtk_secure_entry_new (void)
480
 
{
481
 
  return GTK_WIDGET (gtk_type_new (GTK_TYPE_SECURE_ENTRY));
482
 
}
483
 
 
484
 
GtkWidget*
485
 
gtk_secure_entry_new_with_max_length (guint16 max)
486
 
{
487
 
  GtkSecureEntry *entry;
488
 
 
489
 
  entry = gtk_type_new (GTK_TYPE_SECURE_ENTRY);
490
 
  entry->text_max_length = max;
491
 
 
492
 
  return GTK_WIDGET (entry);
493
 
}
494
 
 
495
 
void
496
 
gtk_secure_entry_set_text (GtkSecureEntry *entry,
497
 
                    const gchar *text)
498
 
{
499
 
  gint tmp_pos;
500
 
 
501
 
  GtkEditable *editable;
502
 
 
503
 
  g_return_if_fail (entry != NULL);
504
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
505
 
  g_return_if_fail (text != NULL);
506
 
 
507
 
  editable = GTK_EDITABLE (entry);
508
 
  
509
 
  gtk_secure_entry_delete_text (GTK_EDITABLE(entry), 0, entry->text_length);
510
 
 
511
 
  tmp_pos = 0;
512
 
  gtk_secure_entry_insert_text (editable, text, strlen (text), &tmp_pos);
513
 
  editable->current_pos = tmp_pos;
514
 
 
515
 
  editable->selection_start_pos = 0;
516
 
  editable->selection_end_pos = 0;
517
 
 
518
 
  if (GTK_WIDGET_DRAWABLE (entry))
519
 
    gtk_secure_entry_draw_text (entry);
520
 
}
521
 
 
522
 
void
523
 
gtk_secure_entry_append_text (GtkSecureEntry *entry,
524
 
                       const gchar *text)
525
 
{
526
 
  gint tmp_pos;
527
 
 
528
 
  g_return_if_fail (entry != NULL);
529
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
530
 
  g_return_if_fail (text != NULL);
531
 
 
532
 
  tmp_pos = entry->text_length;
533
 
  gtk_secure_entry_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
534
 
  GTK_EDITABLE(entry)->current_pos = tmp_pos;
535
 
}
536
 
 
537
 
void
538
 
gtk_secure_entry_prepend_text (GtkSecureEntry *entry,
539
 
                        const gchar *text)
540
 
{
541
 
  gint tmp_pos;
542
 
 
543
 
  g_return_if_fail (entry != NULL);
544
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
545
 
  g_return_if_fail (text != NULL);
546
 
 
547
 
  tmp_pos = 0;
548
 
  gtk_secure_entry_insert_text (GTK_EDITABLE(entry), text, strlen (text), &tmp_pos);
549
 
  GTK_EDITABLE(entry)->current_pos = tmp_pos;
550
 
}
551
 
 
552
 
void
553
 
gtk_secure_entry_set_position (GtkSecureEntry *entry,
554
 
                        gint      position)
555
 
{
556
 
  g_return_if_fail (entry != NULL);
557
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
558
 
 
559
 
  if ((position == -1) || (position > entry->text_length))
560
 
    GTK_EDITABLE(entry)->current_pos = entry->text_length;
561
 
  else
562
 
    GTK_EDITABLE(entry)->current_pos = position;
563
 
  entry_adjust_scroll (entry);
564
 
}
565
 
 
566
 
static void
567
 
gtk_secure_entry_set_position_from_editable (GtkEditable *editable,
568
 
                                      gint position)
569
 
{
570
 
  gtk_secure_entry_set_position (GTK_SECURE_ENTRY (editable), position);
571
 
}
572
 
 
573
 
void
574
 
gtk_secure_entry_set_visibility (GtkSecureEntry *entry,
575
 
                          gboolean visible)
576
 
{
577
 
  g_return_if_fail (entry != NULL);
578
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
579
 
 
580
 
  entry->visible = visible ? TRUE : FALSE;
581
 
  GTK_EDITABLE (entry)->visible = visible ? TRUE : FALSE;
582
 
  gtk_secure_entry_recompute_offsets (entry);
583
 
  gtk_widget_queue_draw (GTK_WIDGET (entry));
584
 
}
585
 
 
586
 
void
587
 
gtk_secure_entry_set_editable(GtkSecureEntry *entry,
588
 
                       gboolean  editable)
589
 
{
590
 
  g_return_if_fail (entry != NULL);
591
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
592
 
 
593
 
  gtk_editable_set_editable (GTK_EDITABLE (entry), editable);
594
 
}
595
 
 
596
 
gchar*
597
 
gtk_secure_entry_get_text (GtkSecureEntry *entry)
598
 
{
599
 
  g_return_val_if_fail (entry != NULL, NULL);
600
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (entry), NULL);
601
 
 
602
 
  if (!entry->text_mb_dirty)
603
 
    return entry->text_mb;
604
 
 
605
 
  if (entry->text_mb)
606
 
    WITH_SECURE_MEM(g_free(entry->text_mb));
607
 
 
608
 
  if (!entry->text)
609
 
    {
610
 
      WITH_SECURE_MEM(entry->text_mb = g_new(gchar, 1));
611
 
      entry->text_mb[0] = 0;
612
 
    }
613
 
  else
614
 
    {
615
 
      entry->text_mb = gtk_secure_entry_get_chars(GTK_EDITABLE(entry), 0, -1);
616
 
    }
617
 
  entry->text_mb_dirty = 0;
618
 
 
619
 
  return entry->text_mb;
620
 
}
621
 
 
622
 
static void
623
 
gtk_secure_entry_finalize (GtkObject *object)
624
 
{
625
 
  GtkSecureEntry *entry;
626
 
 
627
 
  g_return_if_fail (object != NULL);
628
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (object));
629
 
 
630
 
  entry = GTK_SECURE_ENTRY (object);
631
 
 
632
 
  if (entry->timer)
633
 
    gtk_timeout_remove (entry->timer);
634
 
 
635
 
  entry->text_size = 0;
636
 
 
637
 
  if (entry->text)
638
 
    WITH_SECURE_MEM(g_free (entry->text));
639
 
  if (entry->char_offset)
640
 
    g_free (entry->char_offset);
641
 
  entry->text = NULL;
642
 
 
643
 
  if (entry->text_mb)
644
 
    WITH_SECURE_MEM(g_free (entry->text_mb));
645
 
  entry->text_mb = NULL;
646
 
 
647
 
  if (entry->backing_pixmap)
648
 
    gdk_pixmap_unref (entry->backing_pixmap);
649
 
 
650
 
  (* GTK_OBJECT_CLASS (parent_class)->finalize) (object);
651
 
}
652
 
 
653
 
static void
654
 
gtk_secure_entry_realize (GtkWidget *widget)
655
 
{
656
 
  GtkSecureEntry *entry;
657
 
  GtkEditable *editable;
658
 
  GtkRequisition requisition;
659
 
  GdkWindowAttr attributes;
660
 
  gint attributes_mask;
661
 
 
662
 
  g_return_if_fail (widget != NULL);
663
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
664
 
 
665
 
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
666
 
  entry = GTK_SECURE_ENTRY (widget);
667
 
  editable = GTK_EDITABLE (widget);
668
 
 
669
 
  gtk_widget_get_child_requisition (widget, &requisition);
670
 
  
671
 
  attributes.window_type = GDK_WINDOW_CHILD;
672
 
  attributes.x = widget->allocation.x;
673
 
  attributes.y = widget->allocation.y + (widget->allocation.height -
674
 
                                         requisition.height) / 2;
675
 
  attributes.width = widget->allocation.width;
676
 
  attributes.height = requisition.height;
677
 
  attributes.wclass = GDK_INPUT_OUTPUT;
678
 
  attributes.visual = gtk_widget_get_visual (widget);
679
 
  attributes.colormap = gtk_widget_get_colormap (widget);
680
 
  attributes.event_mask = gtk_widget_get_events (widget);
681
 
  attributes.event_mask |= (GDK_EXPOSURE_MASK |
682
 
                            GDK_BUTTON_PRESS_MASK |
683
 
                            GDK_BUTTON_RELEASE_MASK |
684
 
                            GDK_BUTTON1_MOTION_MASK |
685
 
                            GDK_BUTTON3_MOTION_MASK |
686
 
                            GDK_POINTER_MOTION_HINT_MASK |
687
 
                            GDK_ENTER_NOTIFY_MASK |
688
 
                            GDK_LEAVE_NOTIFY_MASK |
689
 
                            GDK_KEY_PRESS_MASK);
690
 
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
691
 
 
692
 
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget), &attributes, attributes_mask);
693
 
  gdk_window_set_user_data (widget->window, entry);
694
 
 
695
 
  attributes.x = widget->style->klass->xthickness;
696
 
  attributes.y = widget->style->klass->ythickness;
697
 
  attributes.width = widget->allocation.width - attributes.x * 2;
698
 
  attributes.height = requisition.height - attributes.y * 2;
699
 
  attributes.cursor = entry->cursor = gdk_cursor_new (GDK_XTERM);
700
 
  attributes_mask |= GDK_WA_CURSOR;
701
 
 
702
 
  entry->text_area = gdk_window_new (widget->window, &attributes, attributes_mask);
703
 
  gdk_window_set_user_data (entry->text_area, entry);
704
 
 
705
 
  widget->style = gtk_style_attach (widget->style, widget->window);
706
 
 
707
 
  gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
708
 
  gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
709
 
 
710
 
#ifdef USE_XIM
711
 
  if (gdk_im_ready () && (editable->ic_attr = gdk_ic_attr_new ()) != NULL)
712
 
    {
713
 
      gint width, height;
714
 
      GdkEventMask mask;
715
 
      GdkColormap *colormap;
716
 
      GdkICAttr *attr = editable->ic_attr;
717
 
      GdkICAttributesType attrmask = GDK_IC_ALL_REQ;
718
 
      GdkIMStyle style;
719
 
      GdkIMStyle supported_style = GDK_IM_PREEDIT_NONE |
720
 
                                   GDK_IM_PREEDIT_NOTHING |
721
 
                                   GDK_IM_PREEDIT_POSITION |
722
 
                                   GDK_IM_STATUS_NONE |
723
 
                                   GDK_IM_STATUS_NOTHING;
724
 
 
725
 
      if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
726
 
        supported_style &= ~GDK_IM_PREEDIT_POSITION;
727
 
 
728
 
      attr->style = style = gdk_im_decide_style (supported_style);
729
 
      attr->client_window = entry->text_area;
730
 
 
731
 
      if ((colormap = gtk_widget_get_colormap (widget)) !=
732
 
            gtk_widget_get_default_colormap ())
733
 
        {
734
 
          attrmask |= GDK_IC_PREEDIT_COLORMAP;
735
 
          attr->preedit_colormap = colormap;
736
 
        }
737
 
      attrmask |= GDK_IC_PREEDIT_FOREGROUND;
738
 
      attrmask |= GDK_IC_PREEDIT_BACKGROUND;
739
 
      attr->preedit_foreground = widget->style->fg[GTK_STATE_NORMAL];
740
 
      attr->preedit_background = widget->style->base[GTK_STATE_NORMAL];
741
 
 
742
 
      switch (style & GDK_IM_PREEDIT_MASK)
743
 
        {
744
 
        case GDK_IM_PREEDIT_POSITION:
745
 
          if (widget->style && widget->style->font->type != GDK_FONT_FONTSET)
746
 
            {
747
 
              g_warning ("over-the-spot style requires fontset");
748
 
              break;
749
 
            }
750
 
 
751
 
          gdk_window_get_size (entry->text_area, &width, &height);
752
 
 
753
 
          attrmask |= GDK_IC_PREEDIT_POSITION_REQ;
754
 
          attr->spot_location.x = 0;
755
 
          attr->spot_location.y = height;
756
 
          attr->preedit_area.x = 0;
757
 
          attr->preedit_area.y = 0;
758
 
          attr->preedit_area.width = width;
759
 
          attr->preedit_area.height = height;
760
 
          attr->preedit_fontset = widget->style->font;
761
 
 
762
 
          break;
763
 
        }
764
 
      editable->ic = gdk_ic_new (attr, attrmask);
765
 
     
766
 
      if (editable->ic == NULL)
767
 
        g_warning ("Can't create input context.");
768
 
      else
769
 
        {
770
 
          mask = gdk_window_get_events (entry->text_area);
771
 
          mask |= gdk_ic_get_events (editable->ic);
772
 
          gdk_window_set_events (entry->text_area, mask);
773
 
 
774
 
          if (GTK_WIDGET_HAS_FOCUS(widget))
775
 
            gdk_im_begin (editable->ic, entry->text_area);
776
 
        }
777
 
    }
778
 
#endif
779
 
 
780
 
  gdk_window_show (entry->text_area);
781
 
 
782
 
  if (editable->selection_start_pos != editable->selection_end_pos)
783
 
    gtk_editable_claim_selection (editable, TRUE, GDK_CURRENT_TIME);
784
 
 
785
 
  gtk_secure_entry_recompute_offsets (entry);
786
 
}
787
 
 
788
 
static void
789
 
gtk_secure_entry_unrealize (GtkWidget *widget)
790
 
{
791
 
  GtkSecureEntry *entry;
792
 
 
793
 
  g_return_if_fail (widget != NULL);
794
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
795
 
 
796
 
  entry = GTK_SECURE_ENTRY (widget);
797
 
 
798
 
#ifdef USE_XIM
799
 
  if (GTK_EDITABLE (widget)->ic)
800
 
    {
801
 
      gdk_ic_destroy (GTK_EDITABLE (widget)->ic);
802
 
      GTK_EDITABLE (widget)->ic = NULL;
803
 
    }
804
 
  if (GTK_EDITABLE (widget)->ic_attr)
805
 
    {
806
 
      gdk_ic_attr_destroy (GTK_EDITABLE (widget)->ic_attr);
807
 
      GTK_EDITABLE (widget)->ic_attr = NULL;
808
 
    }
809
 
#endif
810
 
 
811
 
  if (entry->text_area)
812
 
    {
813
 
      gdk_window_set_user_data (entry->text_area, NULL);
814
 
      gdk_window_destroy (entry->text_area);
815
 
      entry->text_area = NULL;
816
 
      gdk_cursor_destroy (entry->cursor);
817
 
      entry->cursor = NULL;
818
 
    }
819
 
 
820
 
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
821
 
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
822
 
}
823
 
 
824
 
static void
825
 
gtk_secure_entry_draw_focus (GtkWidget *widget)
826
 
{
827
 
  gint width, height;
828
 
  gint x, y;
829
 
 
830
 
  g_return_if_fail (widget != NULL);
831
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
832
 
 
833
 
  if (GTK_WIDGET_DRAWABLE (widget))
834
 
    {
835
 
      x = 0;
836
 
      y = 0;
837
 
      gdk_window_get_size (widget->window, &width, &height);
838
 
 
839
 
      if (GTK_WIDGET_HAS_FOCUS (widget))
840
 
        {
841
 
          x += 1;
842
 
          y += 1;
843
 
          width -= 2;
844
 
          height -= 2;
845
 
        }
846
 
 
847
 
      gtk_paint_shadow (widget->style, widget->window,
848
 
                        GTK_STATE_NORMAL, GTK_SHADOW_IN,
849
 
                        NULL, widget, "entry",
850
 
                        x, y, width, height);
851
 
 
852
 
      if (GTK_WIDGET_HAS_FOCUS (widget))
853
 
        {
854
 
           gdk_window_get_size (widget->window, &width, &height);
855
 
           gtk_paint_focus (widget->style, widget->window, 
856
 
                            NULL, widget, "entry",
857
 
                            0, 0, width - 1, height - 1);
858
 
        }
859
 
 
860
 
      if (GTK_EDITABLE (widget)->editable)
861
 
        gtk_secure_entry_draw_cursor (GTK_SECURE_ENTRY (widget));
862
 
    }
863
 
}
864
 
 
865
 
static void
866
 
gtk_secure_entry_size_request (GtkWidget      *widget,
867
 
                        GtkRequisition *requisition)
868
 
{
869
 
  g_return_if_fail (widget != NULL);
870
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
871
 
  g_return_if_fail (requisition != NULL);
872
 
 
873
 
  requisition->width = MIN_SECURE_ENTRY_WIDTH + (widget->style->klass->xthickness + INNER_BORDER) * 2;
874
 
  requisition->height = (widget->style->font->ascent +
875
 
                         widget->style->font->descent +
876
 
                         (widget->style->klass->ythickness + INNER_BORDER) * 2);
877
 
}
878
 
 
879
 
static void
880
 
gtk_secure_entry_size_allocate (GtkWidget     *widget,
881
 
                         GtkAllocation *allocation)
882
 
{
883
 
  GtkSecureEntry *entry;
884
 
  GtkEditable *editable;
885
 
 
886
 
  g_return_if_fail (widget != NULL);
887
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
888
 
  g_return_if_fail (allocation != NULL);
889
 
 
890
 
  widget->allocation = *allocation;
891
 
  entry = GTK_SECURE_ENTRY (widget);
892
 
  editable = GTK_EDITABLE (widget);
893
 
 
894
 
  if (GTK_WIDGET_REALIZED (widget))
895
 
    {
896
 
      /* We call gtk_widget_get_child_requisition, since we want (for
897
 
       * backwards compatibility reasons) the realization here to
898
 
       * be affected by the usize of the entry, if set
899
 
       */
900
 
      GtkRequisition requisition;
901
 
      gtk_widget_get_child_requisition (widget, &requisition);
902
 
  
903
 
      gdk_window_move_resize (widget->window,
904
 
                              allocation->x,
905
 
                              allocation->y + (allocation->height - requisition.height) / 2,
906
 
                              allocation->width, requisition.height);
907
 
      gdk_window_move_resize (entry->text_area,
908
 
                              widget->style->klass->xthickness,
909
 
                              widget->style->klass->ythickness,
910
 
                              allocation->width - widget->style->klass->xthickness * 2,
911
 
                              requisition.height - widget->style->klass->ythickness * 2);
912
 
 
913
 
      /* And make sure the cursor is on screen */
914
 
      entry_adjust_scroll (entry);
915
 
      
916
 
#ifdef USE_XIM
917
 
      if (editable->ic &&
918
 
          (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION))
919
 
        {
920
 
          gint width, height;
921
 
 
922
 
          gdk_window_get_size (entry->text_area, &width, &height);
923
 
          editable->ic_attr->preedit_area.width = width;
924
 
          editable->ic_attr->preedit_area.height = height;
925
 
          gdk_ic_set_attr (editable->ic, editable->ic_attr,
926
 
                           GDK_IC_PREEDIT_AREA);
927
 
        }
928
 
#endif
929
 
    }
930
 
}
931
 
 
932
 
static void
933
 
gtk_secure_entry_draw (GtkWidget    *widget,
934
 
                GdkRectangle *area)
935
 
{
936
 
  g_return_if_fail (widget != NULL);
937
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
938
 
  g_return_if_fail (area != NULL);
939
 
 
940
 
  if (GTK_WIDGET_DRAWABLE (widget))
941
 
    {
942
 
      gtk_widget_draw_focus (widget);
943
 
      gtk_secure_entry_draw_text (GTK_SECURE_ENTRY (widget));
944
 
    }
945
 
}
946
 
 
947
 
static gint
948
 
gtk_secure_entry_expose (GtkWidget      *widget,
949
 
                  GdkEventExpose *event)
950
 
{
951
 
  GtkSecureEntry *entry;
952
 
 
953
 
  g_return_val_if_fail (widget != NULL, FALSE);
954
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
955
 
  g_return_val_if_fail (event != NULL, FALSE);
956
 
 
957
 
  entry = GTK_SECURE_ENTRY (widget);
958
 
 
959
 
  if (widget->window == event->window)
960
 
    gtk_widget_draw_focus (widget);
961
 
  else if (entry->text_area == event->window)
962
 
    gtk_secure_entry_draw_text (GTK_SECURE_ENTRY (widget));
963
 
 
964
 
  return FALSE;
965
 
}
966
 
 
967
 
static gint
968
 
gtk_secure_entry_button_press (GtkWidget      *widget,
969
 
                        GdkEventButton *event)
970
 
{
971
 
  GtkSecureEntry *entry;
972
 
  GtkEditable *editable;
973
 
  gint tmp_pos;
974
 
 
975
 
  g_return_val_if_fail (widget != NULL, FALSE);
976
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
977
 
  g_return_val_if_fail (event != NULL, FALSE);
978
 
 
979
 
  if (ctext_atom == GDK_NONE)
980
 
    ctext_atom = gdk_atom_intern ("COMPOUND_TEXT", FALSE);
981
 
 
982
 
  entry = GTK_SECURE_ENTRY (widget);
983
 
  editable = GTK_EDITABLE (widget);
984
 
  
985
 
  if (entry->button && (event->button != entry->button))
986
 
    return FALSE;
987
 
 
988
 
  entry->button = event->button;
989
 
  
990
 
  if (!GTK_WIDGET_HAS_FOCUS (widget))
991
 
    gtk_widget_grab_focus (widget);
992
 
 
993
 
  if (event->button == 1)
994
 
    {
995
 
      switch (event->type)
996
 
        {
997
 
        case GDK_BUTTON_PRESS:
998
 
          gtk_grab_add (widget);
999
 
 
1000
 
          tmp_pos = gtk_secure_entry_position (entry, event->x + entry->scroll_offset);
1001
 
          /* Set it now, so we display things right. We'll unset it
1002
 
           * later if things don't work out */
1003
 
          editable->has_selection = TRUE;
1004
 
          gtk_secure_entry_set_selection (editable, tmp_pos, tmp_pos);
1005
 
          editable->current_pos = editable->selection_start_pos;
1006
 
          break;
1007
 
 
1008
 
        case GDK_2BUTTON_PRESS:
1009
 
          gtk_select_word (entry, event->time);
1010
 
          break;
1011
 
 
1012
 
        case GDK_3BUTTON_PRESS:
1013
 
          gtk_select_line (entry, event->time);
1014
 
          break;
1015
 
 
1016
 
        default:
1017
 
          break;
1018
 
        }
1019
 
    }
1020
 
  else if (event->type == GDK_BUTTON_PRESS)
1021
 
    {
1022
 
      if ((event->button == 2) && editable->editable)
1023
 
        {
1024
 
          if (editable->selection_start_pos == editable->selection_end_pos ||
1025
 
              editable->has_selection)
1026
 
            editable->current_pos = gtk_secure_entry_position (entry, event->x + entry->scroll_offset);
1027
 
          gtk_selection_convert (widget, GDK_SELECTION_PRIMARY,
1028
 
                                 ctext_atom, event->time);
1029
 
        }
1030
 
      else
1031
 
        {
1032
 
          gtk_grab_add (widget);
1033
 
 
1034
 
          tmp_pos = gtk_secure_entry_position (entry, event->x + entry->scroll_offset);
1035
 
          gtk_secure_entry_set_selection (editable, tmp_pos, tmp_pos);
1036
 
          editable->has_selection = FALSE;
1037
 
          editable->current_pos = editable->selection_start_pos;
1038
 
 
1039
 
          if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
1040
 
            gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
1041
 
        }
1042
 
    }
1043
 
 
1044
 
  return FALSE;
1045
 
}
1046
 
 
1047
 
static gint
1048
 
gtk_secure_entry_button_release (GtkWidget      *widget,
1049
 
                          GdkEventButton *event)
1050
 
{
1051
 
  GtkSecureEntry *entry;
1052
 
  GtkEditable *editable;
1053
 
 
1054
 
  g_return_val_if_fail (widget != NULL, FALSE);
1055
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
1056
 
  g_return_val_if_fail (event != NULL, FALSE);
1057
 
 
1058
 
  entry = GTK_SECURE_ENTRY (widget);
1059
 
  editable = GTK_EDITABLE (widget);
1060
 
 
1061
 
  if (entry->button != event->button)
1062
 
    return FALSE;
1063
 
 
1064
 
  entry->button = 0;
1065
 
  
1066
 
  if (event->button == 1)
1067
 
    {
1068
 
      gtk_grab_remove (widget);
1069
 
 
1070
 
      editable->has_selection = FALSE;
1071
 
      if (editable->selection_start_pos != editable->selection_end_pos)
1072
 
        {
1073
 
          if (gtk_selection_owner_set (widget,
1074
 
                                       GDK_SELECTION_PRIMARY,
1075
 
                                       event->time))
1076
 
            editable->has_selection = TRUE;
1077
 
          else
1078
 
            gtk_secure_entry_queue_draw (entry);
1079
 
        }
1080
 
      else
1081
 
        {
1082
 
          if (gdk_selection_owner_get (GDK_SELECTION_PRIMARY) == widget->window)
1083
 
            gtk_selection_owner_set (NULL, GDK_SELECTION_PRIMARY, event->time);
1084
 
        }
1085
 
    }
1086
 
  else if (event->button == 3)
1087
 
    {
1088
 
      gtk_grab_remove (widget);
1089
 
    }
1090
 
 
1091
 
  return FALSE;
1092
 
}
1093
 
 
1094
 
static gint
1095
 
gtk_secure_entry_motion_notify (GtkWidget      *widget,
1096
 
                         GdkEventMotion *event)
1097
 
{
1098
 
  GtkSecureEntry *entry;
1099
 
  gint x;
1100
 
 
1101
 
  g_return_val_if_fail (widget != NULL, FALSE);
1102
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
1103
 
  g_return_val_if_fail (event != NULL, FALSE);
1104
 
 
1105
 
  entry = GTK_SECURE_ENTRY (widget);
1106
 
 
1107
 
  if (entry->button == 0)
1108
 
    return FALSE;
1109
 
 
1110
 
  x = event->x;
1111
 
  if (event->is_hint || (entry->text_area != event->window))
1112
 
    gdk_window_get_pointer (entry->text_area, &x, NULL, NULL);
1113
 
 
1114
 
  GTK_EDITABLE(entry)->selection_end_pos = gtk_secure_entry_position (entry, x + entry->scroll_offset);
1115
 
  GTK_EDITABLE(entry)->current_pos = GTK_EDITABLE(entry)->selection_end_pos;
1116
 
  entry_adjust_scroll (entry);
1117
 
  gtk_secure_entry_queue_draw (entry);
1118
 
 
1119
 
  return FALSE;
1120
 
}
1121
 
 
1122
 
static gint
1123
 
gtk_secure_entry_key_press (GtkWidget   *widget,
1124
 
                     GdkEventKey *event)
1125
 
{
1126
 
  GtkSecureEntry *entry;
1127
 
  GtkEditable *editable;
1128
 
 
1129
 
  gint return_val;
1130
 
  gint key;
1131
 
  guint initial_pos;
1132
 
  gint extend_selection;
1133
 
  gint extend_start;
1134
 
 
1135
 
  g_return_val_if_fail (widget != NULL, FALSE);
1136
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
1137
 
  g_return_val_if_fail (event != NULL, FALSE);
1138
 
 
1139
 
  entry = GTK_SECURE_ENTRY (widget);
1140
 
  editable = GTK_EDITABLE (widget);
1141
 
  return_val = FALSE;
1142
 
 
1143
 
  if(editable->editable == FALSE)
1144
 
    return FALSE;
1145
 
 
1146
 
  initial_pos = editable->current_pos;
1147
 
 
1148
 
  extend_selection = event->state & GDK_SHIFT_MASK;
1149
 
  extend_start = FALSE;
1150
 
 
1151
 
  if (extend_selection)
1152
 
    {
1153
 
      if (editable->selection_start_pos == editable->selection_end_pos)
1154
 
        {
1155
 
          editable->selection_start_pos = editable->current_pos;
1156
 
          editable->selection_end_pos = editable->current_pos;
1157
 
        }
1158
 
      
1159
 
      extend_start = (editable->current_pos == editable->selection_start_pos);
1160
 
    }
1161
 
 
1162
 
  switch (event->keyval)
1163
 
    {
1164
 
    case GDK_BackSpace:
1165
 
      return_val = TRUE;
1166
 
      if (event->state & GDK_CONTROL_MASK)
1167
 
        gtk_delete_backward_word (entry);
1168
 
      else
1169
 
        gtk_delete_backward_character (entry);
1170
 
      break;
1171
 
    case GDK_Clear:
1172
 
      return_val = TRUE;
1173
 
      gtk_delete_line (entry);
1174
 
      break;
1175
 
    case GDK_Insert:
1176
 
      return_val = TRUE;
1177
 
      if (event->state & GDK_SHIFT_MASK)
1178
 
        {
1179
 
          extend_selection = FALSE;
1180
 
          gtk_editable_paste_clipboard (editable);
1181
 
        }
1182
 
      else if (event->state & GDK_CONTROL_MASK)
1183
 
        {
1184
 
          gtk_editable_copy_clipboard (editable);
1185
 
        }
1186
 
      else
1187
 
        {
1188
 
          /* gtk_toggle_insert(entry) -- IMPLEMENT */
1189
 
        }
1190
 
      break;
1191
 
    case GDK_Delete:
1192
 
      return_val = TRUE;
1193
 
      if (event->state & GDK_CONTROL_MASK)
1194
 
        gtk_delete_forward_word (entry);
1195
 
      else if (event->state & GDK_SHIFT_MASK)
1196
 
        {
1197
 
          extend_selection = FALSE;
1198
 
          gtk_editable_cut_clipboard (editable);
1199
 
        }
1200
 
      else
1201
 
        gtk_delete_forward_character (entry);
1202
 
      break;
1203
 
    case GDK_Home:
1204
 
      return_val = TRUE;
1205
 
      gtk_move_beginning_of_line (entry);
1206
 
      break;
1207
 
    case GDK_End:
1208
 
      return_val = TRUE;
1209
 
      gtk_move_end_of_line (entry);
1210
 
      break;
1211
 
    case GDK_Left:
1212
 
      return_val = TRUE;
1213
 
      if (event->state & GDK_CONTROL_MASK)
1214
 
        gtk_move_backward_word (entry);
1215
 
      else
1216
 
        gtk_move_backward_character (entry);
1217
 
      break;
1218
 
    case GDK_Right:
1219
 
      return_val = TRUE;
1220
 
      if (event->state & GDK_CONTROL_MASK)
1221
 
        gtk_move_forward_word (entry);
1222
 
      else
1223
 
        gtk_move_forward_character (entry);
1224
 
      break;
1225
 
    case GDK_Return:
1226
 
    case GDK_KP_Enter:
1227
 
      return_val = TRUE;
1228
 
      gtk_widget_activate (widget);
1229
 
      break;
1230
 
    /* The next two keys should not be inserted literally. Any others ??? */
1231
 
    case GDK_Tab:
1232
 
    case GDK_Escape:
1233
 
      break;
1234
 
    default:
1235
 
      if ((event->keyval >= 0x20) && (event->keyval <= 0xFF))
1236
 
        {
1237
 
          key = event->keyval;
1238
 
 
1239
 
          if (event->state & GDK_CONTROL_MASK)
1240
 
            {
1241
 
              if ((key >= 'A') && (key <= 'Z'))
1242
 
                key -= 'A' - 'a';
1243
 
 
1244
 
              if ((key >= 'a') && (key <= 'z') && control_keys[key - 'a'])
1245
 
                {
1246
 
                  (* control_keys[key - 'a']) (editable, event->time);
1247
 
                  return_val = TRUE;
1248
 
                }
1249
 
              break;
1250
 
            }
1251
 
          else if (event->state & GDK_MOD1_MASK)
1252
 
            {
1253
 
              if ((key >= 'A') && (key <= 'Z'))
1254
 
                key -= 'A' - 'a';
1255
 
 
1256
 
              if ((key >= 'a') && (key <= 'z') && alt_keys[key - 'a'])
1257
 
                {
1258
 
                  (* alt_keys[key - 'a']) (editable, event->time);
1259
 
                  return_val = TRUE;
1260
 
                }
1261
 
              break;
1262
 
            }
1263
 
        }
1264
 
      if (event->length > 0)
1265
 
        {
1266
 
          gint tmp_pos;
1267
 
 
1268
 
          extend_selection = FALSE;
1269
 
          gtk_editable_delete_selection (editable);
1270
 
 
1271
 
          tmp_pos = editable->current_pos;
1272
 
          gtk_secure_entry_insert_text (editable, event->string, event->length, &tmp_pos);
1273
 
          editable->current_pos = tmp_pos;
1274
 
 
1275
 
          return_val = TRUE;
1276
 
        }
1277
 
      break;
1278
 
    }
1279
 
 
1280
 
  /* since we emit signals from within the above code,
1281
 
   * the widget might already be destroyed or at least
1282
 
   * unrealized.
1283
 
   */
1284
 
  if (GTK_WIDGET_REALIZED (editable) &&
1285
 
      return_val && (editable->current_pos != initial_pos))
1286
 
    {
1287
 
      if (extend_selection)
1288
 
        {
1289
 
          if (editable->current_pos < editable->selection_start_pos)
1290
 
            editable->selection_start_pos = editable->current_pos;
1291
 
          else if (editable->current_pos > editable->selection_end_pos)
1292
 
            editable->selection_end_pos = editable->current_pos;
1293
 
          else
1294
 
            {
1295
 
              if (extend_start)
1296
 
                editable->selection_start_pos = editable->current_pos;
1297
 
              else
1298
 
                editable->selection_end_pos = editable->current_pos;
1299
 
            }
1300
 
        }
1301
 
      else
1302
 
        {
1303
 
          editable->selection_start_pos = 0;
1304
 
          editable->selection_end_pos = 0;
1305
 
        }
1306
 
 
1307
 
      gtk_editable_claim_selection (editable,
1308
 
                                    editable->selection_start_pos != editable->selection_end_pos,
1309
 
                                    event->time);
1310
 
      
1311
 
      entry_adjust_scroll (entry);
1312
 
      gtk_secure_entry_queue_draw (entry);
1313
 
    }
1314
 
 
1315
 
  return return_val;
1316
 
}
1317
 
 
1318
 
static gint
1319
 
gtk_secure_entry_focus_in (GtkWidget     *widget,
1320
 
                    GdkEventFocus *event)
1321
 
{
1322
 
  g_return_val_if_fail (widget != NULL, FALSE);
1323
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
1324
 
  g_return_val_if_fail (event != NULL, FALSE);
1325
 
 
1326
 
  GTK_WIDGET_SET_FLAGS (widget, GTK_HAS_FOCUS);
1327
 
  gtk_widget_draw_focus (widget);
1328
 
 
1329
 
#ifdef USE_XIM
1330
 
  if (GTK_EDITABLE(widget)->ic)
1331
 
    gdk_im_begin (GTK_EDITABLE(widget)->ic, GTK_SECURE_ENTRY(widget)->text_area);
1332
 
#endif
1333
 
 
1334
 
  return FALSE;
1335
 
}
1336
 
 
1337
 
static gint
1338
 
gtk_secure_entry_focus_out (GtkWidget     *widget,
1339
 
                     GdkEventFocus *event)
1340
 
{
1341
 
  g_return_val_if_fail (widget != NULL, FALSE);
1342
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (widget), FALSE);
1343
 
  g_return_val_if_fail (event != NULL, FALSE);
1344
 
 
1345
 
  GTK_WIDGET_UNSET_FLAGS (widget, GTK_HAS_FOCUS);
1346
 
  gtk_widget_draw_focus (widget);
1347
 
 
1348
 
#ifdef USE_XIM
1349
 
  gdk_im_end ();
1350
 
#endif
1351
 
 
1352
 
  return FALSE;
1353
 
}
1354
 
 
1355
 
static void
1356
 
gtk_secure_entry_make_backing_pixmap (GtkSecureEntry *entry, gint width, gint height)
1357
 
{
1358
 
  gint pixmap_width, pixmap_height;
1359
 
 
1360
 
  if (!entry->backing_pixmap)
1361
 
    {
1362
 
      /* allocate */
1363
 
      entry->backing_pixmap = gdk_pixmap_new (entry->text_area,
1364
 
                                              width, height,
1365
 
                                              -1);
1366
 
    }
1367
 
  else
1368
 
    {
1369
 
      /* reallocate if sizes don't match */
1370
 
      gdk_window_get_size (entry->backing_pixmap,
1371
 
                           &pixmap_width, &pixmap_height);
1372
 
      if ((pixmap_width != width) || (pixmap_height != height))
1373
 
        {
1374
 
          gdk_pixmap_unref (entry->backing_pixmap);
1375
 
          entry->backing_pixmap = gdk_pixmap_new (entry->text_area,
1376
 
                                                  width, height,
1377
 
                                                  -1);
1378
 
        }
1379
 
    }
1380
 
}
1381
 
 
1382
 
static void
1383
 
gtk_secure_entry_draw_text (GtkSecureEntry *entry)
1384
 
{
1385
 
  GtkWidget *widget;
1386
 
  GtkEditable *editable;
1387
 
  GtkStateType selected_state;
1388
 
  gint start_pos;
1389
 
  gint end_pos;
1390
 
  gint start_xoffset;
1391
 
  gint selection_start_pos;
1392
 
  gint selection_end_pos;
1393
 
  gint selection_start_xoffset;
1394
 
  gint selection_end_xoffset;
1395
 
  gint width, height;
1396
 
  gint y;
1397
 
  GdkDrawable *drawable;
1398
 
  gint use_backing_pixmap;
1399
 
  GdkWChar *stars;
1400
 
  GdkWChar *toprint;
1401
 
 
1402
 
  g_return_if_fail (entry != NULL);
1403
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
1404
 
 
1405
 
  if (entry->timer)
1406
 
    {
1407
 
      gtk_timeout_remove (entry->timer);
1408
 
      entry->timer = 0;
1409
 
    }
1410
 
 
1411
 
  if (GTK_WIDGET_DRAWABLE (entry))
1412
 
    {
1413
 
      widget = GTK_WIDGET (entry);
1414
 
      editable = GTK_EDITABLE (entry);
1415
 
 
1416
 
      if (!entry->text)
1417
 
        {         
1418
 
          gtk_paint_flat_box (widget->style, entry->text_area,
1419
 
                              GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
1420
 
                              NULL, widget, "entry_bg", 
1421
 
                              0, 0, -1, -1);
1422
 
 
1423
 
          if (editable->editable)
1424
 
            gtk_secure_entry_draw_cursor (entry);
1425
 
          return;
1426
 
        }
1427
 
 
1428
 
      gdk_window_get_size (entry->text_area, &width, &height);
1429
 
 
1430
 
      /*
1431
 
        If the widget has focus, draw on a backing pixmap to avoid flickering
1432
 
        and copy it to the text_area.
1433
 
        Otherwise draw to text_area directly for better speed.
1434
 
      */
1435
 
      use_backing_pixmap = GTK_WIDGET_HAS_FOCUS (widget) && (entry->text != NULL);
1436
 
      if (use_backing_pixmap)
1437
 
        {
1438
 
           gtk_secure_entry_make_backing_pixmap (entry, width, height);
1439
 
           drawable = entry->backing_pixmap;
1440
 
        }
1441
 
       else
1442
 
         {
1443
 
            drawable = entry->text_area;
1444
 
         }
1445
 
       gtk_paint_flat_box (widget->style, drawable, 
1446
 
                           GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
1447
 
                           NULL, widget, "entry_bg", 
1448
 
                           0, 0, width, height);
1449
 
 
1450
 
      y = (height - (widget->style->font->ascent + widget->style->font->descent)) / 2;
1451
 
      y += widget->style->font->ascent;
1452
 
 
1453
 
      start_pos = gtk_secure_entry_find_position (entry, entry->scroll_offset);
1454
 
      start_xoffset = entry->char_offset[start_pos] - entry->scroll_offset;
1455
 
 
1456
 
      end_pos = gtk_secure_entry_find_position (entry, entry->scroll_offset + width);
1457
 
      if (end_pos < entry->text_length)
1458
 
        end_pos += 1;
1459
 
 
1460
 
      selected_state = GTK_STATE_SELECTED;
1461
 
      if (!editable->has_selection)
1462
 
        selected_state = GTK_STATE_ACTIVE;
1463
 
 
1464
 
      selection_start_pos = MIN (editable->selection_start_pos, editable->selection_end_pos);
1465
 
      selection_end_pos = MAX (editable->selection_start_pos, editable->selection_end_pos);
1466
 
      
1467
 
      selection_start_pos = CLAMP (selection_start_pos, start_pos, end_pos);
1468
 
      selection_end_pos = CLAMP (selection_end_pos, start_pos, end_pos);
1469
 
 
1470
 
      selection_start_xoffset = 
1471
 
        entry->char_offset[selection_start_pos] - entry->scroll_offset;
1472
 
      selection_end_xoffset = 
1473
 
        entry->char_offset[selection_end_pos] -entry->scroll_offset;
1474
 
 
1475
 
      /* if editable->visible, print a bunch of stars.  If not, print the standard text. */
1476
 
      if (editable->visible)
1477
 
        {
1478
 
          toprint = entry->text + start_pos;
1479
 
        }
1480
 
      else
1481
 
        {
1482
 
          gint i;
1483
 
          
1484
 
          stars = g_new (GdkWChar, end_pos - start_pos);
1485
 
          for (i = 0; i < end_pos - start_pos; i++)
1486
 
            stars[i] = '*';
1487
 
          toprint = stars;
1488
 
        }
1489
 
      
1490
 
      if (selection_start_pos > start_pos)
1491
 
        gdk_draw_text_wc (drawable, widget->style->font,
1492
 
                          widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1493
 
                          INNER_BORDER + start_xoffset, y,
1494
 
                          toprint,
1495
 
                          selection_start_pos - start_pos);
1496
 
      
1497
 
      if ((selection_end_pos >= start_pos) && 
1498
 
          (selection_start_pos < end_pos) &&
1499
 
          (selection_start_pos != selection_end_pos))
1500
 
         {
1501
 
            gtk_paint_flat_box (widget->style, drawable, 
1502
 
                                selected_state, GTK_SHADOW_NONE,
1503
 
                                NULL, widget, "text",
1504
 
                                INNER_BORDER + selection_start_xoffset,
1505
 
                                INNER_BORDER,
1506
 
                                selection_end_xoffset - selection_start_xoffset,
1507
 
                                height - 2*INNER_BORDER);
1508
 
            gdk_draw_text_wc (drawable, widget->style->font,
1509
 
                              widget->style->fg_gc[selected_state],
1510
 
                              INNER_BORDER + selection_start_xoffset, y,
1511
 
                              toprint + selection_start_pos - start_pos,
1512
 
                              selection_end_pos - selection_start_pos);
1513
 
         }          
1514
 
       
1515
 
       if (selection_end_pos < end_pos)
1516
 
         gdk_draw_text_wc (drawable, widget->style->font,
1517
 
                           widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1518
 
                           INNER_BORDER + selection_end_xoffset, y,
1519
 
                           toprint + selection_end_pos - start_pos,
1520
 
                           end_pos - selection_end_pos);
1521
 
       /* free the space allocated for the stars if it's neccessary. */
1522
 
      if (!editable->visible)
1523
 
        g_free (toprint);
1524
 
 
1525
 
      if (editable->editable)
1526
 
        gtk_secure_entry_draw_cursor_on_drawable (entry, drawable);
1527
 
 
1528
 
      if (use_backing_pixmap)
1529
 
        gdk_draw_pixmap(entry->text_area,
1530
 
                        widget->style->fg_gc[GTK_STATE_NORMAL],
1531
 
                        entry->backing_pixmap,
1532
 
                        0, 0, 0, 0, width, height);       
1533
 
    }
1534
 
}
1535
 
 
1536
 
static void
1537
 
gtk_secure_entry_draw_cursor (GtkSecureEntry *entry)
1538
 
{
1539
 
  g_return_if_fail (entry != NULL);
1540
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
1541
 
 
1542
 
  gtk_secure_entry_draw_cursor_on_drawable (entry, entry->text_area);
1543
 
}
1544
 
 
1545
 
static void
1546
 
gtk_secure_entry_draw_cursor_on_drawable (GtkSecureEntry *entry, GdkDrawable *drawable)
1547
 
{
1548
 
  GtkWidget *widget;
1549
 
  GtkEditable *editable;
1550
 
  gint xoffset;
1551
 
  gint text_area_height;
1552
 
 
1553
 
  g_return_if_fail (entry != NULL);
1554
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
1555
 
 
1556
 
  if (GTK_WIDGET_DRAWABLE (entry))
1557
 
    {
1558
 
      widget = GTK_WIDGET (entry);
1559
 
      editable = GTK_EDITABLE (entry);
1560
 
 
1561
 
      xoffset = INNER_BORDER + entry->char_offset[editable->current_pos];
1562
 
      xoffset -= entry->scroll_offset;
1563
 
 
1564
 
      gdk_window_get_size (entry->text_area, NULL, &text_area_height);
1565
 
 
1566
 
      if (GTK_WIDGET_HAS_FOCUS (widget) &&
1567
 
          (editable->selection_start_pos == editable->selection_end_pos))
1568
 
        {
1569
 
          gdk_draw_line (drawable, widget->style->fg_gc[GTK_STATE_NORMAL], 
1570
 
                         xoffset, INNER_BORDER,
1571
 
                         xoffset, text_area_height - INNER_BORDER);
1572
 
        }
1573
 
      else
1574
 
        {
1575
 
          gint yoffset = 
1576
 
            (text_area_height - 
1577
 
             (widget->style->font->ascent + widget->style->font->descent)) / 2
1578
 
            + widget->style->font->ascent;
1579
 
 
1580
 
          gtk_paint_flat_box (widget->style, drawable,
1581
 
                              GTK_WIDGET_STATE(widget), GTK_SHADOW_NONE,
1582
 
                              NULL, widget, "entry_bg", 
1583
 
                              xoffset, INNER_BORDER, 
1584
 
                              1, text_area_height - INNER_BORDER);
1585
 
          
1586
 
          /* Draw the character under the cursor again
1587
 
           */
1588
 
          if ((editable->current_pos < entry->text_length) &&
1589
 
              (editable->selection_start_pos == editable->selection_end_pos))
1590
 
            {
1591
 
              GdkWChar c = editable->visible ?
1592
 
                                 *(entry->text + editable->current_pos) :
1593
 
                                 '*';
1594
 
              
1595
 
              gdk_draw_text_wc (drawable, widget->style->font,
1596
 
                                widget->style->fg_gc[GTK_WIDGET_STATE (widget)],
1597
 
                                xoffset, yoffset, &c, 1);
1598
 
            }
1599
 
        }
1600
 
 
1601
 
 
1602
 
#ifdef USE_XIM
1603
 
      if (GTK_WIDGET_HAS_FOCUS(widget) && gdk_im_ready() && editable->ic && 
1604
 
          (gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION))
1605
 
        {
1606
 
          editable->ic_attr->spot_location.x = xoffset;
1607
 
          editable->ic_attr->spot_location.y =
1608
 
            (text_area_height + (widget->style->font->ascent
1609
 
                - widget->style->font->descent) + 1) / 2;
1610
 
 
1611
 
          gdk_ic_set_attr (editable->ic,
1612
 
                           editable->ic_attr, GDK_IC_SPOT_LOCATION);
1613
 
        }
1614
 
#endif 
1615
 
    }
1616
 
}
1617
 
 
1618
 
static void
1619
 
gtk_secure_entry_queue_draw (GtkSecureEntry *entry)
1620
 
{
1621
 
  g_return_if_fail (entry != NULL);
1622
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
1623
 
 
1624
 
  if (!entry->timer)
1625
 
    entry->timer = gtk_timeout_add (DRAW_TIMEOUT, gtk_secure_entry_timer, entry);
1626
 
}
1627
 
 
1628
 
static gint
1629
 
gtk_secure_entry_timer (gpointer data)
1630
 
{
1631
 
  GtkSecureEntry *entry;
1632
 
 
1633
 
  GDK_THREADS_ENTER ();
1634
 
 
1635
 
  entry = GTK_SECURE_ENTRY (data);
1636
 
  entry->timer = 0;
1637
 
  gtk_secure_entry_draw_text (entry);
1638
 
 
1639
 
  GDK_THREADS_LEAVE ();
1640
 
 
1641
 
  return FALSE;
1642
 
}
1643
 
 
1644
 
static gint
1645
 
gtk_secure_entry_find_position (GtkSecureEntry *entry,
1646
 
                         gint      x)
1647
 
{
1648
 
  gint start = 0;
1649
 
  gint end = entry->text_length;
1650
 
  gint half;
1651
 
 
1652
 
  if (x <= 0)
1653
 
    return 0;
1654
 
  if (x >= entry->char_offset[end])
1655
 
    return end;
1656
 
  
1657
 
  /* invariant - char_offset[start] <= x < char_offset[end] */
1658
 
 
1659
 
  while (start != end)
1660
 
    {
1661
 
      half = (start+end)/2;
1662
 
      if (half == start)
1663
 
        return half;
1664
 
      else if (entry->char_offset[half] <= x)
1665
 
        start = half;
1666
 
      else
1667
 
        end = half;
1668
 
    }
1669
 
 
1670
 
  return start;
1671
 
}
1672
 
 
1673
 
static gint
1674
 
gtk_secure_entry_position (GtkSecureEntry *entry,
1675
 
                    gint      x)
1676
 
{
1677
 
  return gtk_secure_entry_find_position(entry, x);
1678
 
}
1679
 
 
1680
 
static void
1681
 
entry_adjust_scroll (GtkSecureEntry *entry)
1682
 
{
1683
 
  gint xoffset, max_offset;
1684
 
  gint text_area_width;
1685
 
 
1686
 
  g_return_if_fail (entry != NULL);
1687
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
1688
 
 
1689
 
  if (!entry->text_area)
1690
 
    return;
1691
 
 
1692
 
  gdk_window_get_size (entry->text_area, &text_area_width, NULL);
1693
 
 
1694
 
  /* Display as much text as we can */
1695
 
  max_offset = MAX(0, entry->char_offset[entry->text_length] - text_area_width);
1696
 
 
1697
 
  if (entry->scroll_offset > max_offset)
1698
 
    entry->scroll_offset = max_offset;
1699
 
 
1700
 
  /* And make sure cursor is on screen */
1701
 
  xoffset = entry->char_offset[GTK_EDITABLE(entry)->current_pos];
1702
 
  xoffset -= entry->scroll_offset;
1703
 
 
1704
 
  if (xoffset < 0)
1705
 
    entry->scroll_offset += xoffset;
1706
 
  else if (xoffset > text_area_width)
1707
 
    entry->scroll_offset += xoffset - text_area_width + 1;
1708
 
 
1709
 
  gtk_widget_queue_draw (GTK_WIDGET (entry));
1710
 
}
1711
 
 
1712
 
static void
1713
 
gtk_secure_entry_grow_text (GtkSecureEntry *entry)
1714
 
{
1715
 
  gint previous_size;
1716
 
  gint i;
1717
 
 
1718
 
  g_return_if_fail (entry != NULL);
1719
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
1720
 
 
1721
 
  previous_size = entry->text_size;
1722
 
  if (!entry->text_size)
1723
 
    entry->text_size = 128;
1724
 
  else
1725
 
    entry->text_size *= 2;
1726
 
  WITH_SECURE_MEM(entry->text = g_realloc (entry->text,
1727
 
                               entry->text_size * sizeof(GdkWChar)));
1728
 
  entry->char_offset = g_realloc (entry->char_offset, 
1729
 
                                  entry->text_size * sizeof(guint));
1730
 
 
1731
 
  if (entry->text_length == 0)  /* initial allocation */
1732
 
    {
1733
 
      entry->char_offset[0] = 0;
1734
 
    }
1735
 
 
1736
 
  for (i = previous_size; i < entry->text_size; i++)
1737
 
    entry->text[i] = '\0';
1738
 
}
1739
 
 
1740
 
static void
1741
 
gtk_secure_entry_insert_text (GtkEditable *editable,
1742
 
                       const gchar *new_text,
1743
 
                       gint         new_text_length,
1744
 
                       gint        *position)
1745
 
{
1746
 
  GdkWChar *text;
1747
 
  gint start_pos;
1748
 
  gint end_pos;
1749
 
  gint last_pos;
1750
 
  gint max_length;
1751
 
  gint i;
1752
 
 
1753
 
  guchar *new_text_nt;
1754
 
  gint insertion_length;
1755
 
  GdkWChar *insertion_text;
1756
 
  
1757
 
  GtkSecureEntry *entry;
1758
 
  GtkWidget *widget;
1759
 
  
1760
 
  g_return_if_fail (editable != NULL);
1761
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (editable));
1762
 
 
1763
 
  entry = GTK_SECURE_ENTRY (editable);
1764
 
  widget = GTK_WIDGET (editable);
1765
 
 
1766
 
  if ((entry->text_length == 0) && (entry->use_wchar == FALSE))
1767
 
    {
1768
 
      if (!GTK_WIDGET_REALIZED (widget))
1769
 
        gtk_widget_ensure_style (widget);
1770
 
      if ((widget->style) && (widget->style->font->type == GDK_FONT_FONTSET))
1771
 
        entry->use_wchar = TRUE;
1772
 
    }
1773
 
 
1774
 
  if (new_text_length < 0)
1775
 
    {
1776
 
      new_text_nt = (gchar *)new_text;
1777
 
      new_text_length = strlen (new_text);
1778
 
      if (new_text_length <= 0) return;
1779
 
    }
1780
 
  else if (new_text_length == 0)
1781
 
    {
1782
 
      return;
1783
 
    }
1784
 
  else
1785
 
    {
1786
 
      /* make a null-terminated copy of new_text */
1787
 
      WITH_SECURE_MEM(new_text_nt = g_new (gchar, new_text_length + 1));
1788
 
      memcpy (new_text_nt, new_text, new_text_length);
1789
 
      new_text_nt[new_text_length] = 0;
1790
 
    }
1791
 
    
1792
 
  /* The algorithms here will work as long as, the text size (a
1793
 
   * multiple of 2), fits into a guint16 but we specify a shorter
1794
 
   * maximum length so that if the user pastes a very long text, there
1795
 
   * is not a long hang from the slow X_LOCALE functions.  */
1796
 
 
1797
 
  if (entry->text_max_length == 0)
1798
 
    max_length = 2047;
1799
 
  else
1800
 
    max_length = MIN (2047, entry->text_max_length);
1801
 
 
1802
 
  /* Convert to wide characters */
1803
 
  WITH_SECURE_MEM(insertion_text = g_new (GdkWChar, new_text_length));
1804
 
  if (entry->use_wchar)
1805
 
    insertion_length = gdk_mbstowcs (insertion_text, new_text_nt,
1806
 
                                     new_text_length);
1807
 
  else
1808
 
    for (insertion_length=0; new_text_nt[insertion_length]; insertion_length++)
1809
 
      insertion_text[insertion_length] = new_text_nt[insertion_length];
1810
 
  if (new_text_nt != (guchar *)new_text)
1811
 
    WITH_SECURE_MEM(g_free (new_text_nt));
1812
 
 
1813
 
  /* Make sure we do not exceed the maximum size of the entry. */
1814
 
  if (insertion_length + entry->text_length > max_length)
1815
 
    insertion_length = max_length - entry->text_length;
1816
 
 
1817
 
  /* Don't insert anything, if there was nothing to insert. */
1818
 
  if (insertion_length <= 0)
1819
 
    {
1820
 
      WITH_SECURE_MEM(g_free(insertion_text));
1821
 
      return;
1822
 
    }
1823
 
 
1824
 
  /* Make sure we are inserting at integral character position */
1825
 
  start_pos = *position;
1826
 
  if (start_pos < 0)
1827
 
    start_pos = 0;
1828
 
  else if (start_pos > entry->text_length)
1829
 
    start_pos = entry->text_length;
1830
 
 
1831
 
  end_pos = start_pos + insertion_length;
1832
 
  last_pos = insertion_length + entry->text_length;
1833
 
 
1834
 
  if (editable->selection_start_pos >= *position)
1835
 
    editable->selection_start_pos += insertion_length;
1836
 
  if (editable->selection_end_pos >= *position)
1837
 
    editable->selection_end_pos += insertion_length;
1838
 
 
1839
 
  while (last_pos >= entry->text_size)
1840
 
    gtk_secure_entry_grow_text (entry);
1841
 
 
1842
 
  text = entry->text;
1843
 
  for (i = last_pos - 1; i >= end_pos; i--)
1844
 
    text[i] = text[i- (end_pos - start_pos)];
1845
 
  for (i = start_pos; i < end_pos; i++)
1846
 
    text[i] = insertion_text[i - start_pos];
1847
 
  WITH_SECURE_MEM(g_free (insertion_text));
1848
 
 
1849
 
  /* Fix up the the character offsets */
1850
 
  
1851
 
  if (GTK_WIDGET_REALIZED (entry))
1852
 
    {
1853
 
      gint offset = 0;
1854
 
      
1855
 
      for (i = last_pos; i >= end_pos; i--)
1856
 
        entry->char_offset[i] 
1857
 
          = entry->char_offset[i - insertion_length];
1858
 
      
1859
 
      for (i=start_pos; i<end_pos; i++)
1860
 
        {
1861
 
          entry->char_offset[i] = entry->char_offset[start_pos] + offset;
1862
 
          if (editable->visible)
1863
 
            {
1864
 
              offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font,
1865
 
                                           entry->text[i]);
1866
 
            }
1867
 
          else
1868
 
            {
1869
 
              offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*');
1870
 
            }
1871
 
        }
1872
 
      for (i = end_pos; i <= last_pos; i++)
1873
 
        entry->char_offset[i] += offset;
1874
 
    }
1875
 
 
1876
 
  entry->text_length += insertion_length;
1877
 
  *position = end_pos;
1878
 
 
1879
 
  entry->text_mb_dirty = 1;
1880
 
  gtk_secure_entry_queue_draw (entry);
1881
 
}
1882
 
 
1883
 
/* Recompute the x offsets of all characters in the buffer */
1884
 
static void
1885
 
gtk_secure_entry_recompute_offsets (GtkSecureEntry *entry)
1886
 
{
1887
 
  gint i;
1888
 
  gint offset = 0;
1889
 
 
1890
 
  for (i=0; i<entry->text_length; i++)
1891
 
    {
1892
 
      entry->char_offset[i] = offset;
1893
 
      if (GTK_EDITABLE (entry)->visible)
1894
 
        {
1895
 
          offset += gdk_char_width_wc (GTK_WIDGET (entry)->style->font,
1896
 
                                       entry->text[i]);
1897
 
        }
1898
 
      else
1899
 
        {
1900
 
          offset += gdk_char_width (GTK_WIDGET (entry)->style->font, '*');
1901
 
        }
1902
 
    }
1903
 
 
1904
 
  entry->char_offset[i] = offset;
1905
 
}
1906
 
 
1907
 
static void
1908
 
gtk_secure_entry_delete_text (GtkEditable *editable,
1909
 
                       gint         start_pos,
1910
 
                       gint         end_pos)
1911
 
{
1912
 
  GdkWChar *text;
1913
 
  gint deletion_length;
1914
 
  gint i;
1915
 
 
1916
 
  GtkSecureEntry *entry;
1917
 
  
1918
 
  g_return_if_fail (editable != NULL);
1919
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (editable));
1920
 
 
1921
 
  entry = GTK_SECURE_ENTRY (editable);
1922
 
 
1923
 
  if (end_pos < 0)
1924
 
    end_pos = entry->text_length;
1925
 
 
1926
 
  if (editable->selection_start_pos > start_pos)
1927
 
    editable->selection_start_pos -= MIN(end_pos, editable->selection_start_pos) - start_pos;
1928
 
  if (editable->selection_end_pos > start_pos)
1929
 
    editable->selection_end_pos -= MIN(end_pos, editable->selection_end_pos) - start_pos;
1930
 
  
1931
 
  if ((start_pos < end_pos) &&
1932
 
      (start_pos >= 0) &&
1933
 
      (end_pos <= entry->text_length))
1934
 
    {
1935
 
      text = entry->text;
1936
 
      deletion_length = end_pos - start_pos;
1937
 
 
1938
 
      /* Fix up the character offsets */
1939
 
      if (GTK_WIDGET_REALIZED (entry))
1940
 
        {
1941
 
          gint deletion_width = 
1942
 
            entry->char_offset[end_pos] - entry->char_offset[start_pos];
1943
 
 
1944
 
          for (i = 0 ; i <= entry->text_length - end_pos; i++)
1945
 
            entry->char_offset[start_pos+i] = entry->char_offset[end_pos+i] - deletion_width;
1946
 
        }
1947
 
 
1948
 
      for (i = end_pos; i < entry->text_length; i++)
1949
 
        text[i - deletion_length] = text[i];
1950
 
 
1951
 
      for (i = entry->text_length - deletion_length; i < entry->text_length; i++)
1952
 
        text[i] = '\0';
1953
 
 
1954
 
      entry->text_length -= deletion_length;
1955
 
      editable->current_pos = start_pos;
1956
 
    }
1957
 
 
1958
 
  entry->text_mb_dirty = 1;
1959
 
  gtk_secure_entry_queue_draw (entry);
1960
 
}
1961
 
 
1962
 
static void
1963
 
gtk_secure_entry_update_text (GtkEditable *editable,
1964
 
                       gint         start_pos,
1965
 
                       gint         end_pos)
1966
 
{
1967
 
  gtk_secure_entry_queue_draw (GTK_SECURE_ENTRY(editable));
1968
 
}
1969
 
 
1970
 
static gchar *    
1971
 
gtk_secure_entry_get_chars      (GtkEditable   *editable,
1972
 
                          gint           start_pos,
1973
 
                          gint           end_pos)
1974
 
{
1975
 
  GtkSecureEntry *entry;
1976
 
  
1977
 
  g_return_val_if_fail (editable != NULL, NULL);
1978
 
  g_return_val_if_fail (GTK_IS_SECURE_ENTRY (editable), NULL);
1979
 
 
1980
 
  entry = GTK_SECURE_ENTRY (editable);
1981
 
 
1982
 
  if (end_pos < 0)
1983
 
    end_pos = entry->text_length;
1984
 
 
1985
 
  start_pos = MIN(entry->text_length, start_pos);
1986
 
  end_pos = MIN(entry->text_length, end_pos);
1987
 
 
1988
 
  if (start_pos <= end_pos)
1989
 
    {
1990
 
      guchar *mbstr;
1991
 
      if (entry->use_wchar)
1992
 
        {
1993
 
          GdkWChar ch;
1994
 
          if (end_pos >= entry->text_size)
1995
 
            gtk_secure_entry_grow_text(entry);
1996
 
          ch = entry->text[end_pos];
1997
 
          entry->text[end_pos] = 0;
1998
 
          WITH_SECURE_MEM(mbstr = gdk_wcstombs (entry->text + start_pos));
1999
 
          entry->text[end_pos] = ch;
2000
 
          return (gchar *)mbstr;
2001
 
        }
2002
 
      else
2003
 
        {
2004
 
          gint i;
2005
 
          WITH_SECURE_MEM(mbstr = g_new (gchar, end_pos - start_pos + 1));
2006
 
          for (i=0; i<end_pos-start_pos; i++)
2007
 
            mbstr[i] = entry->text[start_pos + i];
2008
 
          mbstr[i] = 0;
2009
 
          return (gchar *)mbstr;
2010
 
        }
2011
 
    }
2012
 
  else
2013
 
    return NULL;
2014
 
}
2015
 
 
2016
 
static void 
2017
 
gtk_secure_entry_move_cursor (GtkEditable *editable,
2018
 
                       gint         x,
2019
 
                       gint         y)
2020
 
{
2021
 
  GtkSecureEntry *entry;
2022
 
  entry = GTK_SECURE_ENTRY (editable);
2023
 
 
2024
 
  /* Horizontal motion */
2025
 
  if ((gint)editable->current_pos < -x)
2026
 
    editable->current_pos = 0;
2027
 
  else if (editable->current_pos + x > entry->text_length)
2028
 
    editable->current_pos = entry->text_length;
2029
 
  else
2030
 
    editable->current_pos += x;
2031
 
 
2032
 
  /* Ignore vertical motion */
2033
 
}
2034
 
 
2035
 
static void
2036
 
gtk_move_forward_character (GtkSecureEntry *entry)
2037
 
{
2038
 
  gtk_secure_entry_move_cursor (GTK_EDITABLE (entry), 1, 0);
2039
 
}
2040
 
 
2041
 
static void
2042
 
gtk_move_backward_character (GtkSecureEntry *entry)
2043
 
{
2044
 
  gtk_secure_entry_move_cursor (GTK_EDITABLE (entry), -1, 0);
2045
 
}
2046
 
 
2047
 
static void 
2048
 
gtk_secure_entry_move_word (GtkEditable *editable,
2049
 
                     gint         n)
2050
 
{
2051
 
  while (n-- > 0)
2052
 
    gtk_move_forward_word (GTK_SECURE_ENTRY (editable));
2053
 
  while (n++ < 0)
2054
 
    gtk_move_backward_word (GTK_SECURE_ENTRY (editable));
2055
 
}
2056
 
 
2057
 
static void
2058
 
gtk_move_forward_word (GtkSecureEntry *entry)
2059
 
{
2060
 
  GtkEditable *editable;
2061
 
  GdkWChar *text;
2062
 
  gint i;
2063
 
 
2064
 
  editable = GTK_EDITABLE (entry);
2065
 
 
2066
 
  if (entry->text && (editable->current_pos < entry->text_length))
2067
 
    {
2068
 
      text = entry->text;
2069
 
      i = editable->current_pos;
2070
 
          
2071
 
      if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
2072
 
        for (; i < entry->text_length; i++)
2073
 
          {
2074
 
            if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i]))
2075
 
              break;
2076
 
          }
2077
 
 
2078
 
      for (; i < entry->text_length; i++)
2079
 
        {
2080
 
          if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
2081
 
            break;
2082
 
        }
2083
 
 
2084
 
      editable->current_pos = i;
2085
 
    }
2086
 
}
2087
 
 
2088
 
static void
2089
 
gtk_move_backward_word (GtkSecureEntry *entry)
2090
 
{
2091
 
  GtkEditable *editable;
2092
 
  GdkWChar *text;
2093
 
  gint i;
2094
 
 
2095
 
  editable = GTK_EDITABLE (entry);
2096
 
 
2097
 
  if (entry->text && editable->current_pos > 0)
2098
 
    {
2099
 
      text = entry->text;
2100
 
      i = editable->current_pos - 1;
2101
 
      if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
2102
 
        for (; i >= 0; i--)
2103
 
          {
2104
 
            if ((entry->use_wchar) ? gdk_iswalnum (text[i]) : isalnum (text[i]))
2105
 
              break;
2106
 
          }
2107
 
      for (; i >= 0; i--)
2108
 
        {
2109
 
          if ((entry->use_wchar) ? (!gdk_iswalnum (text[i])) : (!isalnum (text[i])))
2110
 
            {
2111
 
              i++;
2112
 
              break;
2113
 
            }
2114
 
        }
2115
 
          
2116
 
      if (i < 0)
2117
 
        i = 0;
2118
 
          
2119
 
      editable->current_pos = i;
2120
 
    }
2121
 
}
2122
 
 
2123
 
static void
2124
 
gtk_secure_entry_move_to_column (GtkEditable *editable, gint column)
2125
 
{
2126
 
  GtkSecureEntry *entry;
2127
 
 
2128
 
  entry = GTK_SECURE_ENTRY (editable);
2129
 
  
2130
 
  if (column < 0 || column > entry->text_length)
2131
 
    editable->current_pos = entry->text_length;
2132
 
  else
2133
 
    editable->current_pos = column;
2134
 
}
2135
 
 
2136
 
static void
2137
 
gtk_move_beginning_of_line (GtkSecureEntry *entry)
2138
 
{
2139
 
  gtk_secure_entry_move_to_column (GTK_EDITABLE (entry), 0);
2140
 
}
2141
 
 
2142
 
static void
2143
 
gtk_move_end_of_line (GtkSecureEntry *entry)
2144
 
{
2145
 
  gtk_secure_entry_move_to_column (GTK_EDITABLE (entry), -1);
2146
 
}
2147
 
 
2148
 
static void
2149
 
gtk_secure_entry_kill_char (GtkEditable *editable,
2150
 
                     gint         direction)
2151
 
{
2152
 
  if (editable->selection_start_pos != editable->selection_end_pos)
2153
 
    gtk_editable_delete_selection (editable);
2154
 
  else
2155
 
    {
2156
 
      gint old_pos = editable->current_pos;
2157
 
      if (direction >= 0)
2158
 
        {
2159
 
          gtk_secure_entry_move_cursor (editable, 1, 0);
2160
 
          gtk_editable_delete_text (editable, old_pos, editable->current_pos);
2161
 
        }
2162
 
      else
2163
 
        {
2164
 
          gtk_secure_entry_move_cursor (editable, -1, 0);
2165
 
          gtk_editable_delete_text (editable, editable->current_pos, old_pos);
2166
 
        }
2167
 
    }
2168
 
}
2169
 
 
2170
 
static void
2171
 
gtk_delete_forward_character (GtkSecureEntry *entry)
2172
 
{
2173
 
  gtk_secure_entry_kill_char (GTK_EDITABLE (entry), 1);
2174
 
}
2175
 
 
2176
 
static void
2177
 
gtk_delete_backward_character (GtkSecureEntry *entry)
2178
 
{
2179
 
  gtk_secure_entry_kill_char (GTK_EDITABLE (entry), -1);
2180
 
}
2181
 
 
2182
 
static void
2183
 
gtk_secure_entry_kill_word (GtkEditable *editable,
2184
 
                     gint         direction)
2185
 
{
2186
 
  if (editable->selection_start_pos != editable->selection_end_pos)
2187
 
    gtk_editable_delete_selection (editable);
2188
 
  else
2189
 
    {
2190
 
      gint old_pos = editable->current_pos;
2191
 
      if (direction >= 0)
2192
 
        {
2193
 
          gtk_secure_entry_move_word (editable, 1);
2194
 
          gtk_editable_delete_text (editable, old_pos, editable->current_pos);
2195
 
        }
2196
 
      else
2197
 
        {
2198
 
          gtk_secure_entry_move_word (editable, -1);
2199
 
          gtk_editable_delete_text (editable, editable->current_pos, old_pos);
2200
 
        }
2201
 
    }
2202
 
}
2203
 
 
2204
 
static void
2205
 
gtk_delete_forward_word (GtkSecureEntry *entry)
2206
 
{
2207
 
  gtk_secure_entry_kill_word (GTK_EDITABLE (entry), 1);
2208
 
}
2209
 
 
2210
 
static void
2211
 
gtk_delete_backward_word (GtkSecureEntry *entry)
2212
 
{
2213
 
  gtk_secure_entry_kill_word (GTK_EDITABLE (entry), -1);
2214
 
}
2215
 
 
2216
 
static void
2217
 
gtk_secure_entry_kill_line (GtkEditable *editable,
2218
 
                     gint         direction)
2219
 
{
2220
 
  gint old_pos = editable->current_pos;
2221
 
  if (direction >= 0)
2222
 
    {
2223
 
      gtk_secure_entry_move_to_column (editable, -1);
2224
 
      gtk_editable_delete_text (editable, old_pos, editable->current_pos);
2225
 
    }
2226
 
  else
2227
 
    {
2228
 
      gtk_secure_entry_move_to_column (editable, 0);
2229
 
      gtk_editable_delete_text (editable, editable->current_pos, old_pos);
2230
 
    }
2231
 
}
2232
 
 
2233
 
static void
2234
 
gtk_delete_line (GtkSecureEntry *entry)
2235
 
{
2236
 
  gtk_secure_entry_move_to_column (GTK_EDITABLE (entry), 0);
2237
 
  gtk_secure_entry_kill_line (GTK_EDITABLE (entry), 1);
2238
 
}
2239
 
 
2240
 
static void
2241
 
gtk_delete_to_line_end (GtkSecureEntry *entry)
2242
 
{
2243
 
  gtk_editable_delete_text (GTK_EDITABLE(entry), GTK_EDITABLE(entry)->current_pos, entry->text_length);
2244
 
}
2245
 
 
2246
 
static void
2247
 
gtk_select_word (GtkSecureEntry *entry,
2248
 
                 guint32   time)
2249
 
{
2250
 
  GtkEditable *editable;
2251
 
  gint start_pos;
2252
 
  gint end_pos;
2253
 
 
2254
 
  editable = GTK_EDITABLE (entry);
2255
 
 
2256
 
  gtk_move_backward_word (entry);
2257
 
  start_pos = editable->current_pos;
2258
 
 
2259
 
  gtk_move_forward_word (entry);
2260
 
  end_pos = editable->current_pos;
2261
 
 
2262
 
  editable->has_selection = TRUE;
2263
 
  gtk_secure_entry_set_selection (editable, start_pos, end_pos);
2264
 
  gtk_editable_claim_selection (editable, start_pos != end_pos, time);
2265
 
}
2266
 
 
2267
 
static void
2268
 
gtk_select_line (GtkSecureEntry *entry,
2269
 
                 guint32   time)
2270
 
{
2271
 
  GtkEditable *editable;
2272
 
 
2273
 
  editable = GTK_EDITABLE (entry);
2274
 
 
2275
 
  editable->has_selection = TRUE;
2276
 
  gtk_secure_entry_set_selection (editable, 0, entry->text_length);
2277
 
  gtk_editable_claim_selection (editable, entry->text_length != 0, time);
2278
 
 
2279
 
  editable->current_pos = editable->selection_end_pos;
2280
 
}
2281
 
 
2282
 
static void 
2283
 
gtk_secure_entry_set_selection (GtkEditable       *editable,
2284
 
                         gint               start,
2285
 
                         gint               end)
2286
 
{
2287
 
  g_return_if_fail (editable != NULL);
2288
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (editable));
2289
 
 
2290
 
  if (end < 0)
2291
 
    end = GTK_SECURE_ENTRY (editable)->text_length;
2292
 
  
2293
 
  editable->selection_start_pos = start;
2294
 
  editable->selection_end_pos = end;
2295
 
 
2296
 
  gtk_secure_entry_queue_draw (GTK_SECURE_ENTRY (editable));
2297
 
}
2298
 
 
2299
 
void       
2300
 
gtk_secure_entry_select_region  (GtkSecureEntry       *entry,
2301
 
                          gint            start,
2302
 
                          gint            end)
2303
 
{
2304
 
  gtk_editable_select_region (GTK_EDITABLE (entry), start, end);
2305
 
}
2306
 
 
2307
 
void
2308
 
gtk_secure_entry_set_max_length (GtkSecureEntry     *entry,
2309
 
                          guint16       max)
2310
 
{
2311
 
  g_return_if_fail (entry != NULL);
2312
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (entry));
2313
 
 
2314
 
  if (max && entry->text_length > max)
2315
 
        gtk_editable_delete_text(GTK_EDITABLE(entry), max, -1);
2316
 
  entry->text_max_length = max;
2317
 
}
2318
 
 
2319
 
#ifdef USE_XIM
2320
 
static void
2321
 
gtk_secure_entry_update_ic_attr (GtkWidget *widget)
2322
 
{
2323
 
  GtkEditable *editable = (GtkEditable *) widget;
2324
 
  GdkICAttributesType mask = 0;
2325
 
 
2326
 
  if (editable->ic == NULL)
2327
 
    return;
2328
 
 
2329
 
  gdk_ic_get_attr (editable->ic, editable->ic_attr,
2330
 
                   GDK_IC_PREEDIT_FOREGROUND |
2331
 
                   GDK_IC_PREEDIT_BACKGROUND |
2332
 
                   GDK_IC_PREEDIT_FONTSET);
2333
 
 
2334
 
  if (editable->ic_attr->preedit_foreground.pixel != 
2335
 
      widget->style->fg[GTK_STATE_NORMAL].pixel)
2336
 
    {
2337
 
      mask |= GDK_IC_PREEDIT_FOREGROUND;
2338
 
      editable->ic_attr->preedit_foreground
2339
 
        = widget->style->fg[GTK_STATE_NORMAL];
2340
 
    }
2341
 
  if (editable->ic_attr->preedit_background.pixel != 
2342
 
      widget->style->base[GTK_STATE_NORMAL].pixel)
2343
 
    {
2344
 
      mask |= GDK_IC_PREEDIT_BACKGROUND;
2345
 
      editable->ic_attr->preedit_background
2346
 
        = widget->style->base[GTK_STATE_NORMAL];
2347
 
    }
2348
 
  if ((gdk_ic_get_style (editable->ic) & GDK_IM_PREEDIT_POSITION) && 
2349
 
      widget->style->font != NULL &&
2350
 
      widget->style->font->type == GDK_FONT_FONTSET &&
2351
 
      !gdk_font_equal (editable->ic_attr->preedit_fontset,
2352
 
                       widget->style->font))
2353
 
    {
2354
 
      mask |= GDK_IC_PREEDIT_FONTSET;
2355
 
      editable->ic_attr->preedit_fontset = widget->style->font;
2356
 
    }
2357
 
  
2358
 
  if (mask)
2359
 
    gdk_ic_set_attr (editable->ic, editable->ic_attr, mask);
2360
 
}
2361
 
#endif /* USE_XIM */
2362
 
                          
2363
 
static void 
2364
 
gtk_secure_entry_style_set      (GtkWidget      *widget,
2365
 
                         GtkStyle       *previous_style)
2366
 
{
2367
 
  GtkSecureEntry *entry;
2368
 
  gint scroll_char;
2369
 
 
2370
 
  g_return_if_fail (widget != NULL);
2371
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
2372
 
 
2373
 
  if (previous_style && GTK_WIDGET_REALIZED (widget))
2374
 
    {
2375
 
      entry = GTK_SECURE_ENTRY (widget);
2376
 
  
2377
 
      scroll_char = gtk_secure_entry_find_position (entry, entry->scroll_offset);
2378
 
      gtk_secure_entry_recompute_offsets (GTK_SECURE_ENTRY (widget));
2379
 
      entry->scroll_offset = entry->char_offset[scroll_char];
2380
 
      entry_adjust_scroll (entry);
2381
 
 
2382
 
      gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2383
 
      gdk_window_set_background (entry->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2384
 
 
2385
 
#ifdef USE_XIM
2386
 
      gtk_secure_entry_update_ic_attr (widget);
2387
 
#endif
2388
 
    }
2389
 
}
2390
 
 
2391
 
static void
2392
 
gtk_secure_entry_state_changed (GtkWidget      *widget,
2393
 
                         GtkStateType    previous_state)
2394
 
{
2395
 
  g_return_if_fail (widget != NULL);
2396
 
  g_return_if_fail (GTK_IS_SECURE_ENTRY (widget));
2397
 
 
2398
 
  if (GTK_WIDGET_REALIZED (widget))
2399
 
    {
2400
 
      gdk_window_set_background (widget->window, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2401
 
      gdk_window_set_background (GTK_SECURE_ENTRY (widget)->text_area, &widget->style->base[GTK_WIDGET_STATE (widget)]);
2402
 
 
2403
 
#ifdef USE_XIM
2404
 
      gtk_secure_entry_update_ic_attr (widget);
2405
 
#endif
2406
 
    }
2407
 
 
2408
 
  if (GTK_WIDGET_DRAWABLE (widget))
2409
 
    gtk_widget_queue_clear(widget);
2410
 
}