Bug 161885 - [calendar] incorrect cursor movement and delete for indic charcters
[calendar] incorrect cursor movement and delete for indic charcters
Status: CLOSED RAWHIDE
Product: Fedora
Classification: Fedora
Component: evolution (Show other bugs)
6
All Linux
low Severity medium
: ---
: ---
Assigned To: Matthew Barnes
: i18n
Depends On:
Blocks:
  Show dependency treegraph
 
Reported: 2005-06-28 00:41 EDT by Lawrence Lim
Modified: 2014-03-25 20:52 EDT (History)
7 users (show)

See Also:
Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Story Points: ---
Clone Of:
Environment:
Last Closed: 2007-10-05 00:48:48 EDT
Type: ---
Regression: ---
Mount Type: ---
Documentation: ---
CRM:
Verified Versions:
Category: ---
oVirt Team: ---
RHEL 7.3 requirements from Atomic Host:
Cloudforms Team: ---


Attachments (Terms of Use)
Problem description (70.03 KB, image/png)
2006-05-16 06:46 EDT, Mayank Jain
no flags Details
patch for the bug (5.32 KB, patch)
2006-08-04 09:59 EDT, Mayank Jain
no flags Details | Diff
Modified patch (5.46 KB, patch)
2006-08-04 11:28 EDT, Mayank Jain
no flags Details | Diff
New patch with bugs corrected (6.22 KB, patch)
2006-08-07 06:20 EDT, Mayank Jain
no flags Details | Diff
screenshot (225.30 KB, image/png)
2006-09-29 04:41 EDT, Xiaohong Wang
no flags Details
Working patch, with backspacing problem fixed. (9.05 KB, patch)
2006-11-09 06:05 EST, Mayank Jain
no flags Details | Diff


External Trackers
Tracker ID Priority Status Summary Last Updated
GNOME Desktop 309166 None None None Never

  None (edit)
Description Lawrence Lim 2005-06-28 00:41:31 EDT
Description of problem:
While inputting indic languages in the evolution calendar, composite glyphs and
ligatures are considered as independent glyphs during cursor navigation. For
example, while moving the cursor left to right on a single glyph composed from 4
unicode characters, the cursor has to be moved 4 times, instead of once.
Similarly, deletion happens one unicode character at a time, instead of deleting
the full glyph. This behaviour is inconsistent with the rest of the gnome desktop
(compare to gedit).

Version-Release number of selected component (if applicable):
evolution-2.2.2-8
evolution-data-server-1.2.2-3
libgal2-2.4.2-5

How reproducible:
Always

Steps to Reproduce:
1.in g-t, LANG=pa_IN.UTF-8 evolution
2.select Calendar
3.click on any of the time slot
4.press a, backspace
5.ctrl-space
6.ugkg
7.move cursor from the right to left using the arrow keys
  
Actual results:
takes two keypress to move across one composed character and two Delete keys to
remove one composed character

Expected results:
the cursor movement and Delete should be similar to Gtk+, one key press to move
across a single composed character and one key press (Delete) to remove a
composed character.

Additional info:
Comment 1 Lawrence Lim 2005-06-28 00:53:27 EDT
Bug has been filed upstream. 

http://bugzilla.gnome.org/show_bug.cgi?id=309166
Comment 2 Lawrence Lim 2005-06-28 00:59:35 EDT
Same problem in Evolution Task as well, should I open a new bug to track it?
Comment 3 Dave Malcolm 2005-08-23 21:30:47 EDT
Please can you specify which view of the calendar you see this behaviour in
(they are implemented in different ways).

Probably worth filing separately for Tasks as well.

Thanks
Comment 5 Mayank Jain 2006-05-16 06:46:50 EDT
Created attachment 129169 [details]
Problem description

The problem description
Comment 6 A S Alam 2006-05-22 07:30:11 EDT
bug is till exist

Test with following packages
---------------------------
evolution-sharp-0.11.1-1
evolution-data-server-1.7.1-2
evolution-webcal-2.4.1-3.2
evolution-2.7.1-1
evolution-data-server-devel-1.7.1-2
---------------------------
Comment 7 Mayank Jain 2006-08-04 07:33:52 EDT
Just an update...

Moving cursor across "ਹ" is not atall a problem... but things start getting
messy when "ੁ" (a vowel) is also added to "ਹ".

So the problem is with all vowels (dependent or independent)

Also, the functions of interest are
_get_position and e_text_command in $evo/widgets/text/e-text.c

Modelling the text widget on the way gtkentry manages movement inside the buffer
would be an ideal way.
Comment 8 Mayank Jain 2006-08-04 09:59:15 EDT
Created attachment 133636 [details]
patch for the bug

Patch to correct the bug
Comment 9 Mayank Jain 2006-08-04 10:07:15 EDT
This is what basically what the patch does...

- Get a list of PangoLogAttrs for the text associated with text widget
- Move forward/backward as necessary (as per key press)
- If new position has log_attr.is_cursor_position set, its the right position to
display the cursor, hence return its position. Else, goto previous step.
Comment 10 Mayank Jain 2006-08-04 10:11:33 EDT
Changing component to Evolution.
Comment 11 Mayank Jain 2006-08-04 11:28:19 EDT
Created attachment 133639 [details]
Modified patch

Updated patch for more robust error handling & code abstraction.
Moved duplicate code into a function.
Comment 12 Mayank Jain 2006-08-07 06:20:02 EDT
Created attachment 133722 [details]
New patch with bugs corrected
Comment 13 Mayank Jain 2006-09-02 08:53:11 EDT
Matthew, same with this bug... Since upstream bugsweep would be a bit too late
to include patch in http://bugzilla.gnome.org/show_bug.cgi?id=309166#c6 can you
please test this patch & then we can push it in rawhide.

BTW, is it a good practise to push a patch in rawhide, before it gets tested in
upstream bugsweep?

Tagoh san, considering the progress of this bug upstream, can you please give
some guidance?

Thanks,
Mayank
Comment 14 Matthew Barnes 2006-09-12 16:45:51 EDT
Hi Mayank,

Sorry, I think this one fell between the cracks.  If it's okay with you I'm
going to hold off on committing this until after Fedora Core 6 is out.

Normally, when we're not in a test freeze, I push patches to Rawhide after I'm
reasonably sure that it works correctly.  Upstream is swamped with bugs and
doesn't always get around to reviewing patches in a timely manner.  Putting it
in Rawhide gets it out in the wild for the early adopters to try out, which
actually helps out the upstream developers in the end.
Comment 16 Matthew Barnes 2006-09-13 09:57:18 EDT
Fair enough, I wasn't aware of the importance of it.  I'll try to squeeze it in.
Comment 17 Mayank Jain 2006-09-13 10:27:15 EDT
Thanks a lot Matthew :)
Comment 18 Matthew Barnes 2006-09-13 17:02:56 EDT
Patch applied to evolution-2.8.0-3.fc6.

Should be available in Rawhide after the FC6Test3 freeze ends.

Looks good as far as I can tell, but I'll let you close this bug once you're
satisfied that the patch is working correctly.
Comment 19 Mayank Jain 2006-09-14 02:55:09 EDT
Thanks Matthew.
Since the status is now already MODIFIED, QE can test it in their bug sweep &
then close or assign this bug back to us as required.

:)
Mayank
Comment 20 Xiaohong Wang 2006-09-29 04:40:56 EDT
Verified in latest FC6:
# rpm -q evolution
evolution-2.8.0-6.fc6

Evolution got crashed in step 3.click on any of the time slot

pls see attached screenshot
Comment 21 Xiaohong Wang 2006-09-29 04:42:02 EDT
Created attachment 137374 [details]
screenshot
Comment 22 Mayank Jain 2006-09-29 07:05:57 EDT
> Evolution got crashed in step 3.click on any of the time slot
Hi, Can you please double check this?

I have 3 rawhide machines & I could not crash evolution on any 3 with step 3.
Comment 23 Xiaohong Wang 2006-10-10 03:42:51 EDT
Sorry for delayed response because of long holiday leave.
I retest in latest evolution-2.8.0-7.fc6, if just one click in step 3. The
cursor movement and Delete work fine after step 7.

But if double click in step 3, evolution may get crashed. Here I have 2 rawhide
machines could reproduce this.

Comment 24 Mayank Jain 2006-10-10 05:50:51 EDT
Hmm... i rechecked this. & it IS crashing.
Thanks for your testing.

The GDB backtrace is as follows... actually, this freezes my desktop & i had to
gdb backtrace from an ssh connection.

----------------START----------------
Program received signal SIGSEGV, Segmentation fault.
[Switching to Thread -1209002288 (LWP 10938)]
0x006c0986 in parse_with_strptime (value=0x94ab5a0 "�/�\a�ݮ�",
result=0xbfaee820, formats=0xbfaee7cc, n_formats=3) at e-time-utils.c:1499
1499            while (isspace (*pos))
(gdb) bt
#0  0x006c0986 in parse_with_strptime (value=0x94ab5a0 "�/�\a�ݮ�",
result=0xbfaee820, formats=0xbfaee7cc, n_formats=3) at e-time-utils.c:1499
#1  0x006c0bbc in e_time_parse_date (value=0x94ab5a0 "�/�\a�ݮ�",
result=0xbfaee820) at e-time-utils.c:1731
#2  0x001357f3 in e_date_edit_parse_date (dedit=0xb7f016a0, date_text=0xb7cc6018
"\002", date_tm=0x0) at e-dateedit.c:1470
#3  0x0013586c in e_date_edit_check_date_changed (dedit=0x94a98a0) at
e-dateedit.c:1853
#4  0x00136619 in e_date_edit_get_date (dedit=0x94a98a0, year=0xbfaee8e4,
month=0xbfaee8e8, day=0xbfaee8ec) at e-dateedit.c:689
#5  0x01d9ea1a in update_end_time_selector (epage=0x949d7a0) at event-page.c:1591
#6  0x01d9f093 in init_widgets (epage=0x949d7a0) at event-page.c:2913
#7  0x01d9f633 in event_page_construct (epage=0x949d7a0, model=0x9402528,
client=0x922a990) at event-page.c:3092
#8  0x01da189d in event_page_new (model=0x9402528, client=0x922a990,
uic=0x9272d80) at event-page.c:3115
#9  0x01d9cbf0 in event_editor_construct (ee=0x9061450, client=0x922a990) at
event-editor.c:559
#10 0x01d9d243 in event_editor_new (client=0x922a990,
flags=COMP_EDITOR_NEW_ITEM) at event-editor.c:842
#11 0x01d35391 in open_event_with_flags (cal_view=0x91f3a88, client=0x922a990,
icalcomp=0x90e86a0, flags=1) at e-calendar-view.c:1962
#12 0x01d3665d in e_calendar_view_new_appointment_for (cal_view=0x91f3a88,
dtstart=1160546400, dtend=1160548200, all_day=0, meeting=0)
    at e-calendar-view.c:1901
#13 0x01d523b0 in e_day_view_on_main_canvas_button_press (widget=0x91d6470,
event=0x927caa0, day_view=0x91f3a88) at e-day-view.c:3524
#14 0x010d800d in _gtk_marshal_BOOLEAN__BOXED (closure=0x91f60a8,
return_value=0xbfaeed68, n_param_values=2, param_values=0xbfaeede8, 
    invocation_hint=0xbfaeed54, marshal_data=0x1d522cd) at gtkmarshalers.c:84
#15 0x003a1a5e in IA__g_closure_invoke (closure=0x91f60a8,
return_value=0xbfaeed68, n_param_values=2, param_values=0xbfaeede8,
invocation_hint=0xbfaeed54)
    at gclosure.c:490
#16 0x003adb9f in signal_emit_unlocked_R (node=0x90220b8, detail=0,
instance=0x91d6470, emission_return=0xbfaeefa8, instance_and_params=0xbfaeede8)
    at gsignal.c:2440
#17 0x003ae708 in IA__g_signal_emit_valist (instance=0x91d6470, signal_id=59,
detail=0, 
    var_args=0xbfaef010 "8���pd\035\tH����\025\033\001pd\035\t
��\b��\016\t��\016\ttd\035\t\001") at gsignal.c:2209
#18 0x003aea0b in IA__g_signal_emit (instance=0x91d6470, signal_id=59, detail=0)
at gsignal.c:2243
#19 0x011b1761 in gtk_widget_event_internal (widget=0x91d6470, event=0x927caa0)
at gtkwidget.c:3911
#20 0x010d2bad in IA__gtk_propagate_event (widget=0x91d6470, event=0x927caa0) at
gtkmain.c:2188
#21 0x010d3ae3 in IA__gtk_main_do_event (event=0x927caa0) at gtkmain.c:1422
#22 0x008192c4 in gdk_event_dispatch (source=0x8f51ca8, callback=0,
user_data=0x0) at gdkevents-x11.c:2320
#23 0x00523ed8 in g_main_dispatch (context=0x8f51cf0) at gmain.c:2045
#24 0x0052405d in IA__g_main_context_dispatch (context=0x8f51cf0) at gmain.c:2596
#25 0x00525aee in g_main_context_iterate (context=0x8f51cf0, block=1,
dispatch=1, self=0x8f350a8) at gmain.c:2677
#26 0x00526887 in IA__g_main_loop_run (loop=0x8fa27a0) at gmain.c:2881
#27 0x02eaba23 in bonobo_main () from /usr/lib/libbonobo-2.so.0
#28 0x08059009 in main (argc=1, argv=0xbfaef2b4) at main.c:615
(gdb) 

----------------END----------------
Comment 25 Mayank Jain 2006-10-10 05:53:43 EDT
----------------START----------------
(gdb) thread apply all bt

Thread 4 (Thread 41737104 (LWP 11028)):
#0  0x00fd9402 in __kernel_vsyscall ()
#1  0x07f0d503 in poll () from /lib/libc.so.6
#2  0x00522a03 in g_main_context_poll (context=<value optimized out>,
timeout=-1, priority=1, fds=0x947ef40, n_fds=1) at gmain.c:2979
#3  0x00525aca in g_main_context_iterate (context=0x947eae8, block=1,
dispatch=1, self=0x947e778) at gmain.c:2672
#4  0x00526887 in IA__g_main_loop_run (loop=0x947bb30) at gmain.c:2881
#5  0x001f3bd6 in startup_mainloop (arg=0x0) at e-book.c:3760
#6  0x00539e53 in g_thread_create_proxy (data=0x947e778) at gthread.c:553
#7  0x006743db in start_thread () from /lib/libpthread.so.0
#8  0x07f1706e in clone () from /lib/libc.so.6

Thread 3 (Thread 94354320 (LWP 11027)):
#0  0x00fd9402 in __kernel_vsyscall ()
#1  0x0067842c in pthread_cond_timedwait@@GLIBC_2.3.2 () from /lib/libpthread.so.0
#2  0x00315bc9 in g_cond_timed_wait_posix_impl (cond=0x9231bc8,
entered_mutex=0x0, abs_time=0x45) at gthread-posix.c:231
#3  0x0050d02e in g_async_queue_pop_intern_unlocked (queue=0x8f52f80, try=0,
end_time=0x59fb358) at gasyncqueue.c:341
#4  0x0053b0b6 in g_thread_pool_wait_for_new_task (pool=0x8f52f48) at
gthreadpool.c:220
#5  0x0053b21f in g_thread_pool_thread_proxy (data=0x8f52f48) at gthreadpool.c:254
#6  0x00539e53 in g_thread_create_proxy (data=0x90e8678) at gthread.c:553
#7  0x006743db in start_thread () from /lib/libpthread.so.0
#8  0x07f1706e in clone () from /lib/libc.so.6

Thread 2 (Thread 20982672 (LWP 10970)):
#0  0x00fd9402 in __kernel_vsyscall ()
#1  0x07f0d503 in poll () from /lib/libc.so.6
#2  0x00522a03 in g_main_context_poll (context=<value optimized out>,
timeout=-1, priority=9, fds=0x9233c38, n_fds=9) at gmain.c:2979
#3  0x00525aca in g_main_context_iterate (context=0x92189f0, block=1,
dispatch=1, self=0x9230ad8) at gmain.c:2672
#4  0x00526887 in IA__g_main_loop_run (loop=0x91f5790) at gmain.c:2881
#5  0x02cdb2e0 in link_set_io_thread () from /usr/lib/libORBit-2.so.0
#6  0x00539e53 in g_thread_create_proxy (data=0x9230ad8) at gthread.c:553
#7  0x006743db in start_thread () from /lib/libpthread.so.0
#8  0x07f1706e in clone () from /lib/libc.so.6

Thread 1 (Thread -1209002288 (LWP 10938)):
#0  0x006c0986 in parse_with_strptime (value=0x94ab5a0 "�/�\a�ݮ�",
result=0xbfaee820, formats=0xbfaee7cc, n_formats=3) at e-time-utils.c:1499
#1  0x006c0bbc in e_time_parse_date (value=0x94ab5a0 "�/�\a�ݮ�",
result=0xbfaee820) at e-time-utils.c:1731
#2  0x001357f3 in e_date_edit_parse_date (dedit=0xb7f016a0, date_text=0xb7cc6018
"\002", date_tm=0x0) at e-dateedit.c:1470
#3  0x0013586c in e_date_edit_check_date_changed (dedit=0x94a98a0) at
e-dateedit.c:1853
#4  0x00136619 in e_date_edit_get_date (dedit=0x94a98a0, year=0xbfaee8e4,
month=0xbfaee8e8, day=0xbfaee8ec) at e-dateedit.c:689
#5  0x01d9ea1a in update_end_time_selector (epage=0x949d7a0) at event-page.c:1591
#6  0x01d9f093 in init_widgets (epage=0x949d7a0) at event-page.c:2913
#7  0x01d9f633 in event_page_construct (epage=0x949d7a0, model=0x9402528,
client=0x922a990) at event-page.c:3092
#8  0x01da189d in event_page_new (model=0x9402528, client=0x922a990,
uic=0x9272d80) at event-page.c:3115
#9  0x01d9cbf0 in event_editor_construct (ee=0x9061450, client=0x922a990) at
event-editor.c:559
#10 0x01d9d243 in event_editor_new (client=0x922a990,
flags=COMP_EDITOR_NEW_ITEM) at event-editor.c:842
#11 0x01d35391 in open_event_with_flags (cal_view=0x91f3a88, client=0x922a990,
icalcomp=0x90e86a0, flags=1) at e-calendar-view.c:1962
#12 0x01d3665d in e_calendar_view_new_appointment_for (cal_view=0x91f3a88,
dtstart=1160546400, dtend=1160548200, all_day=0, meeting=0)
    at e-calendar-view.c:1901
#13 0x01d523b0 in e_day_view_on_main_canvas_button_press (widget=0x91d6470,
event=0x927caa0, day_view=0x91f3a88) at e-day-view.c:3524
#14 0x010d800d in _gtk_marshal_BOOLEAN__BOXED (closure=0x91f60a8,
return_value=0xbfaeed68, n_param_values=2, param_values=0xbfaeede8, 
    invocation_hint=0xbfaeed54, marshal_data=0x1d522cd) at gtkmarshalers.c:84
#15 0x003a1a5e in IA__g_closure_invoke (closure=0x91f60a8,
return_value=0xbfaeed68, n_param_values=2, param_values=0xbfaeede8,
invocation_hint=0xbfaeed54)
---Type <return> to continue, or q <return> to quit---
    at gclosure.c:490
#16 0x003adb9f in signal_emit_unlocked_R (node=0x90220b8, detail=0,
instance=0x91d6470, emission_return=0xbfaeefa8, instance_and_params=0xbfaeede8)
    at gsignal.c:2440
#17 0x003ae708 in IA__g_signal_emit_valist (instance=0x91d6470, signal_id=59,
detail=0, 
    var_args=0xbfaef010 "8���pd\035\tH����\025\033\001pd\035\t
��\b��\016\t��\016\ttd\035\t\001") at gsignal.c:2209
#18 0x003aea0b in IA__g_signal_emit (instance=0x91d6470, signal_id=59, detail=0)
at gsignal.c:2243
#19 0x011b1761 in gtk_widget_event_internal (widget=0x91d6470, event=0x927caa0)
at gtkwidget.c:3911
#20 0x010d2bad in IA__gtk_propagate_event (widget=0x91d6470, event=0x927caa0) at
gtkmain.c:2188
#21 0x010d3ae3 in IA__gtk_main_do_event (event=0x927caa0) at gtkmain.c:1422
#22 0x008192c4 in gdk_event_dispatch (source=0x8f51ca8, callback=0,
user_data=0x0) at gdkevents-x11.c:2320
#23 0x00523ed8 in g_main_dispatch (context=0x8f51cf0) at gmain.c:2045
#24 0x0052405d in IA__g_main_context_dispatch (context=0x8f51cf0) at gmain.c:2596
#25 0x00525aee in g_main_context_iterate (context=0x8f51cf0, block=1,
dispatch=1, self=0x8f350a8) at gmain.c:2677
#26 0x00526887 in IA__g_main_loop_run (loop=0x8fa27a0) at gmain.c:2881
#27 0x02eaba23 in bonobo_main () from /usr/lib/libbonobo-2.so.0
#28 0x08059009 in main (argc=1, argv=0xbfaef2b4) at main.c:615
(gdb) 
----------------END----------------
Comment 26 Mayank Jain 2006-10-10 07:48:20 EDT
The double click is the culprit here...
Comment 27 Mayank Jain 2006-10-10 08:30:51 EDT
After some investigation i've found that the crash is happening if i disable
this patch & its happening even in a fresh cvs fetch from upstream.

xwang, can you please file a new bug for this - downstream & an upstream bug &
link them?

PS: pls let me know how can I address you if xwang is not the correct way.

Thanks,
Mayank
Comment 28 Mayank Jain 2006-10-10 09:19:12 EDT
Bug 210142 filed for problem mentioned in comment 20

Based on comment 27, this bug can be closed/modified independently from problem
mentioned in comment 20
Comment 29 Mayank Jain 2006-10-12 02:27:23 EDT
Hi Matthew, as per comment 18, since we've already applied this patch in the
rpm, we should move this to MODIFIED :)

Bug 210142 will take care of the problem mentioned in comment 20
Comment 30 Matthew Barnes 2006-10-12 07:29:22 EDT
Okay, changing status to MODIFIED.
Comment 31 Mayank Jain 2006-10-12 07:46:28 EDT
Thanks
Comment 32 Mayank Jain 2006-11-09 06:02:55 EST
Comment From Nicole Dai (ndai@redhat.com)  	

1. Click a time slot input 'ugkg' by Punjabi Inscript, then move cursor from the
right to left using the arrow keys, it takes one keypress to move across one
composed character. Then click 'Delete' key, it takes one Delete key to remove
one composed character. (Work fine)

2. Click a time slot input 'ugkg' by Punjabi Inscript, then click 'Backspace',it
takes ONE Backspace key to remove one composed character. (not same as gedit)

3. Double-click a time slot,in the Summary on the pop up window, input 'ugkg' by
Punjabi Inscript,then move cursor from the right to left using the arrow keys,
it takes one keypress to move across one composed character. Then click 'Delete'
key, it takes one Delete key to remove one composed character. (Work fine)

4. Double-click a time slot,in the Summary on the pop up window, input 'ugkg' by
Punjabi Inscript, then click 'Backspace', it takes TWO Backspace key to remove
one composed character. (same as gedit)

--- based on this comment, reopening the bug
Comment 33 Mayank Jain 2006-11-09 06:03:50 EST
With current patch

"""
		/* check before moving forward/backwards if we have more chars to move or not */
		if(TRUE == direction)
			p = g_utf8_next_char (p);
		else
			p = g_utf8_prev_char (p);
"""

The last line "p = g_utf8_prev_char (p);" causes the cursor to delete full one
grapheme cluster, causing "ਹੁ" to get deleted.

However, If I change this last line to "new_pos = text->selection_end - 1;" then
delete works fine, but the original bug starts to reappear.

Hence I'm trying to find a way to simultaneously solve both of the problems.

Comment 34 Mayank Jain 2006-11-09 06:05:01 EST
Created attachment 140755 [details]
Working patch, with backspacing problem fixed.

Updated patch, creates a new command.position value as...

"""
/* Backspace is handled separately so as to fix movement across a grapheme
cluster in indic languages */				     
command.position = E_TEP_BACKSPACE_CHARACTER;
""" 

This patch is based on the logic mentioned in the previous comment.

Matthew, please check.

Thanks,
Mayank
Comment 35 Mayank Jain 2006-11-09 06:06:57 EST
Assigning it back to you Matthew :)
Comment 36 Mayank Jain 2007-02-23 04:55:35 EST
Hi Matthew,

If the patch in Comment 34 is already in Rawhide, can you please set this to
MODIFIED?

Thanks :)
Comment 37 Matthew Barnes 2007-10-05 00:48:48 EDT
Fixed this upstream recently.  Released in Evolution 2.12.0.

Note You need to log in before you can comment on or make changes to this bug.