From bfd7362e2afe74c68ecb42eaa7cdc6a520332116 Mon Sep 17 00:00:00 2001 From: James Booth Date: Sat, 12 Jan 2013 01:34:09 +0000 Subject: [PATCH] Renamed muc functions --- src/command.c | 8 +- src/jabber.c | 34 ++-- src/muc.c | 436 ++++++++++++++++++++++++------------------------ src/muc.h | 52 +++--- src/profanity.c | 10 +- src/windows.c | 10 +- 6 files changed, 277 insertions(+), 273 deletions(-) diff --git a/src/command.c b/src/command.c index 37b14ae1..82374b3a 100644 --- a/src/command.c +++ b/src/command.c @@ -771,7 +771,7 @@ cmd_reset_autocomplete() p_autocomplete_reset(sub_ac); if (win_current_is_groupchat()) { - PAutocomplete nick_ac = room_get_nick_ac(win_current_get_recipient()); + PAutocomplete nick_ac = muc_get_roster_ac(win_current_get_recipient()); if (nick_ac != NULL) { p_autocomplete_reset(nick_ac); } @@ -916,7 +916,7 @@ _cmd_complete_parameters(char *input, int *size) prefs_autocomplete_boolean_choice); if (win_current_is_groupchat()) { - PAutocomplete nick_ac = room_get_nick_ac(win_current_get_recipient()); + PAutocomplete nick_ac = muc_get_roster_ac(win_current_get_recipient()); if (nick_ac != NULL) { _parameter_autocomplete_with_ac(input, size, "/msg", nick_ac); _parameter_autocomplete_with_ac(input, size, "/info", nick_ac); @@ -1534,7 +1534,7 @@ _cmd_msg(gchar **args, struct cmd_help_t help) if (win_current_is_groupchat()) { char *room_name = win_current_get_recipient(); - if (room_nick_in_roster(room_name, usr)) { + if (muc_nick_in_roster(room_name, usr)) { GString *full_jid = g_string_new(room_name); g_string_append(full_jid, "/"); g_string_append(full_jid, usr); @@ -1614,7 +1614,7 @@ _cmd_join(gchar **args, struct cmd_help_t help) strcpy(jid_cpy, jid); nick = strdup(strtok(jid_cpy, "@")); } - if (!room_is_active(room)) { + if (!muc_room_is_active(room)) { jabber_join(room, nick); } win_join_chat(room, nick); diff --git a/src/jabber.c b/src/jabber.c index bc67d2c1..790037f6 100644 --- a/src/jabber.c +++ b/src/jabber.c @@ -355,7 +355,7 @@ jabber_join(const char * const room, const char * const nick) xmpp_send(jabber_conn.conn, presence); xmpp_stanza_release(presence); - room_join(room, nick); + muc_join_room(room, nick); free(full_room_jid); } @@ -375,7 +375,7 @@ jabber_change_room_nick(const char * const room, const char * const nick) void jabber_leave_chat_room(const char * const room_jid) { - char *nick = room_get_nick_for_room(room_jid); + char *nick = muc_get_room_nick(room_jid); xmpp_stanza_t *presence = stanza_create_room_leave_presence(jabber_conn.ctx, room_jid, nick); @@ -454,10 +454,10 @@ jabber_update_presence(jabber_presence_t status, const char * const msg, xmpp_send(jabber_conn.conn, presence); // send presence for each room - GList *rooms = room_get_rooms(); + GList *rooms = muc_get_active_room_list(); while (rooms != NULL) { char *room = rooms->data; - char *nick = room_get_nick_for_room(room); + char *nick = muc_get_room_nick(room); char *full_room_jid = room_create_full_room_jid(room, nick); xmpp_stanza_set_attribute(presence, STANZA_ATTR_TO, full_room_jid); @@ -609,7 +609,7 @@ _groupchat_message_handler(xmpp_stanza_t * const stanza) } // room not active in profanity - if (!room_is_active(room_jid)) { + if (!muc_room_is_active(room_jid)) { log_error("Message recieved for inactive groupchat: %s", room_jid); g_free(room); g_free(nick); @@ -686,7 +686,7 @@ _chat_message_handler(xmpp_stanza_t * const stanza) char *jid = NULL; // private message from chat room use full jid (room/nick) - if (room_is_active(short_from)) { + if (muc_room_is_active(short_from)) { jid = strdup(from); priv = TRUE; // standard chat message, use jid without resource @@ -994,18 +994,18 @@ _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) // leave room if not self nick change if (nick_change) { - room_set_pending_nick_change(room); + muc_set_room_pending_nick_change(room); } else { prof_handle_leave_room(room); } // handle self nick change - } else if (room_is_pending_nick_change(room)) { - room_change_nick(room, nick); + } else if (muc_is_room_pending_nick_change(room)) { + muc_complete_room_nick_change(room, nick); prof_handle_room_nick_change(room, nick); // handle roster complete - } else if (!room_get_roster_received(room)) { + } else if (!muc_get_roster_received(room)) { prof_handle_room_roster_complete(room); } @@ -1027,7 +1027,7 @@ _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) // handle nickname change if (stanza_is_room_nick_change(stanza)) { char *new_nick = stanza_get_new_nick(stanza); - room_add_pending_nick_change(room, new_nick, nick); + muc_set_roster_pending_nick_change(room, new_nick, nick); } else { prof_handle_room_member_offline(room, nick, "offline", status_str); } @@ -1038,16 +1038,16 @@ _room_presence_handler(const char * const jid, xmpp_stanza_t * const stanza) } else { show_str = "online"; } - if (!room_get_roster_received(room)) { - room_add_to_roster(room, nick, show_str, status_str); + if (!muc_get_roster_received(room)) { + muc_add_to_roster(room, nick, show_str, status_str); } else { - char *old_nick = room_complete_pending_nick_change(room, nick); + char *old_nick = muc_complete_roster_nick_change(room, nick); if (old_nick != NULL) { - room_add_to_roster(room, nick, show_str, status_str); + muc_add_to_roster(room, nick, show_str, status_str); prof_handle_room_member_nick_change(room, old_nick, nick); } else { - if (!room_nick_in_roster(room, nick)) { + if (!muc_nick_in_roster(room, nick)) { prof_handle_room_member_online(room, nick, show_str, status_str); } else { prof_handle_room_member_presence(room, nick, show_str, status_str); @@ -1077,7 +1077,7 @@ _presence_handler(xmpp_conn_t * const conn, } // handle chat room presence - if (room_is_active(from)) { + if (muc_room_is_active(from)) { return _room_presence_handler(from, stanza); // handle regular presence diff --git a/src/muc.c b/src/muc.c index da9d6522..171f4085 100644 --- a/src/muc.c +++ b/src/muc.c @@ -41,17 +41,17 @@ typedef struct _muc_room_t { GHashTable *rooms = NULL; -static void _room_free(muc_room *room); +static void _free_room(muc_room *room); /* * Join the chat room with the specified nickname */ void -room_join(const char * const room, const char * const nick) +muc_join_room(const char * const room, const char * const nick) { if (rooms == NULL) { rooms = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, - (GDestroyNotify)_room_free); + (GDestroyNotify)_free_room); } muc_room *new_room = malloc(sizeof(muc_room)); @@ -72,62 +72,16 @@ room_join(const char * const room, const char * const nick) * Leave the room */ void -room_leave(const char * const room) +muc_leave_room(const char * const room) { g_hash_table_remove(rooms, room); } -/* - * Flag that the user has sent a nick change to the service - * and is awaiting the response - */ -void -room_set_pending_nick_change(const char * const room) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - chat_room->pending_nick_change = TRUE; - } -} - -/* - * Returns TRUE if the room is awaiting the result of a - * nick change - */ -gboolean -room_is_pending_nick_change(const char * const room) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - return chat_room->pending_nick_change; - } else { - return FALSE; - } -} - -/* - * Change the current nuck name for the room, call once - * the service has responded - */ -void -room_change_nick(const char * const room, const char * const nick) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - free(chat_room->nick); - chat_room->nick = strdup(nick); - chat_room->pending_nick_change = FALSE; - } -} - /* * Returns TRUE if the user is currently in the room */ gboolean -room_is_active(const char * const full_room_jid) +muc_room_is_active(const char * const full_room_jid) { char **tokens = g_strsplit(full_room_jid, "/", 0); char *room_part = tokens[0]; @@ -145,13 +99,59 @@ room_is_active(const char * const full_room_jid) } } +/* + * Flag that the user has sent a nick change to the service + * and is awaiting the response + */ +void +muc_set_room_pending_nick_change(const char * const room) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + chat_room->pending_nick_change = TRUE; + } +} + +/* + * Returns TRUE if the room is awaiting the result of a + * nick change + */ +gboolean +muc_is_room_pending_nick_change(const char * const room) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + return chat_room->pending_nick_change; + } else { + return FALSE; + } +} + +/* + * Change the current nuck name for the room, call once + * the service has responded + */ +void +muc_complete_room_nick_change(const char * const room, const char * const nick) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + free(chat_room->nick); + chat_room->nick = strdup(nick); + chat_room->pending_nick_change = FALSE; + } +} + /* * Return a list of room names * The contents of the list are owned by the chat room and should not be * modified or freed. */ GList * -room_get_rooms(void) +muc_get_active_room_list(void) { if (rooms != NULL) { return g_hash_table_get_keys(rooms); @@ -165,7 +165,7 @@ room_get_rooms(void) * The nickname is owned by the chat room and should not be modified or freed */ char * -room_get_nick_for_room(const char * const room) +muc_get_room_nick(const char * const room) { if (rooms != NULL) { muc_room *chat_room = g_hash_table_lookup(rooms, room); @@ -180,6 +180,170 @@ room_get_nick_for_room(const char * const room) } } +/* + * Returns TRUE if the specified nick exists in the room's roster + */ +gboolean +muc_nick_in_roster(const char * const room, const char * const nick) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + PContact contact = g_hash_table_lookup(chat_room->roster, nick); + if (contact != NULL) { + return TRUE; + } else { + return FALSE; + } + } + + return FALSE; +} + +/* + * Add a new chat room member to the room's roster + */ +gboolean +muc_add_to_roster(const char * const room, const char * const nick, + const char * const show, const char * const status) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + gboolean updated = FALSE; + + if (chat_room != NULL) { + PContact old = g_hash_table_lookup(chat_room->roster, nick); + + if (old == NULL) { + updated = TRUE; + p_autocomplete_add(chat_room->nick_ac, strdup(nick)); + } else if ((g_strcmp0(p_contact_presence(old), show) != 0) || + (g_strcmp0(p_contact_status(old), status) != 0)) { + updated = TRUE; + } + + PContact contact = p_contact_new(nick, NULL, show, status, NULL, FALSE); + g_hash_table_replace(chat_room->roster, strdup(nick), contact); + } + + return updated; +} + +/* + * Remove a room member from the room's roster + */ +void +muc_remove_from_roster(const char * const room, const char * const nick) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + g_hash_table_remove(chat_room->roster, nick); + p_autocomplete_remove(chat_room->nick_ac, nick); + } +} + +/* + * Return a list of PContacts representing the room members in the room's roster + * The list is owned by the room and must not be mofified or freed + */ +GList * +muc_get_roster(const char * const room) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + return g_hash_table_get_values(chat_room->roster); + } else { + return NULL; + } +} + +/* + * Return a PAutocomplete representing the room member's in the roster + */ +PAutocomplete +muc_get_roster_ac(const char * const room) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + return chat_room->nick_ac; + } else { + return NULL; + } +} + +/* + * Set to TRUE when the rooms roster has been fully recieved + */ +void +muc_set_roster_received(const char * const room) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + chat_room->roster_received = TRUE; + } +} + +/* + * Returns TRUE id the rooms roster has been fully recieved + */ +gboolean +muc_get_roster_received(const char * const room) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + return chat_room->roster_received; + } else { + return FALSE; + } +} + +/* + * Remove the old_nick from the roster, and flag that a pending nickname change + * is in progress + */ +void +muc_set_roster_pending_nick_change(const char * const room, + const char * const new_nick, const char * const old_nick) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + g_hash_table_insert(chat_room->nick_changes, strdup(new_nick), strdup(old_nick)); + muc_remove_from_roster(room, old_nick); + } +} + +/* + * Complete the pending nick name change for a contact in the room's roster + * The new nick name will be added to the roster + * The old nick name will be returned in a new string which must be freed by + * the caller + */ +char * +muc_complete_roster_nick_change(const char * const room, + const char * const nick) +{ + muc_room *chat_room = g_hash_table_lookup(rooms, room); + + if (chat_room != NULL) { + char *old_nick = g_hash_table_lookup(chat_room->nick_changes, nick); + char *old_nick_cpy; + + if (old_nick != NULL) { + old_nick_cpy = strdup(old_nick); + g_hash_table_remove(chat_room->nick_changes, nick); + + return old_nick_cpy; + } + } + + return NULL; +} + /* * Get the room name part of the full JID, e.g. * Full JID = "test@conference.server/person" @@ -279,172 +443,8 @@ room_parse_room_jid(const char * const full_room_jid, char **room, char **nick) } } -/* - * Returns TRUE if the specified nick exists in the room's roster - */ -gboolean -room_nick_in_roster(const char * const room, const char * const nick) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - PContact contact = g_hash_table_lookup(chat_room->roster, nick); - if (contact != NULL) { - return TRUE; - } else { - return FALSE; - } - } - - return FALSE; -} - -/* - * Add a new chat room member to the room's roster - */ -gboolean -room_add_to_roster(const char * const room, const char * const nick, - const char * const show, const char * const status) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - gboolean updated = FALSE; - - if (chat_room != NULL) { - PContact old = g_hash_table_lookup(chat_room->roster, nick); - - if (old == NULL) { - updated = TRUE; - p_autocomplete_add(chat_room->nick_ac, strdup(nick)); - } else if ((g_strcmp0(p_contact_presence(old), show) != 0) || - (g_strcmp0(p_contact_status(old), status) != 0)) { - updated = TRUE; - } - - PContact contact = p_contact_new(nick, NULL, show, status, NULL, FALSE); - g_hash_table_replace(chat_room->roster, strdup(nick), contact); - } - - return updated; -} - -/* - * Remove a room member from the room's roster - */ -void -room_remove_from_roster(const char * const room, const char * const nick) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - g_hash_table_remove(chat_room->roster, nick); - p_autocomplete_remove(chat_room->nick_ac, nick); - } -} - -/* - * Return a list of PContacts representing the room members in the room's roster - * The list is owned by the room and must not be mofified or freed - */ -GList * -room_get_roster(const char * const room) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - return g_hash_table_get_values(chat_room->roster); - } else { - return NULL; - } -} - -/* - * Return a PAutocomplete representing the room member's in the roster - */ -PAutocomplete -room_get_nick_ac(const char * const room) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - return chat_room->nick_ac; - } else { - return NULL; - } -} - -/* - * Set to TRUE when the rooms roster has been fully recieved - */ -void -room_set_roster_received(const char * const room) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - chat_room->roster_received = TRUE; - } -} - -/* - * Returns TRUE id the rooms roster has been fully recieved - */ -gboolean -room_get_roster_received(const char * const room) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - return chat_room->roster_received; - } else { - return FALSE; - } -} - -/* - * Remove the old_nick from the roster, and flag that a pending nickname change - * is in progress - */ -void -room_add_pending_nick_change(const char * const room, - const char * const new_nick, const char * const old_nick) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - g_hash_table_insert(chat_room->nick_changes, strdup(new_nick), strdup(old_nick)); - room_remove_from_roster(room, old_nick); - } -} - -/* - * Complete the pending nick name change for a contact in the room's roster - * The new nick name will be added to the roster - * The old nick name will be returned in a new string which must be freed by - * the caller - */ -char * -room_complete_pending_nick_change(const char * const room, - const char * const nick) -{ - muc_room *chat_room = g_hash_table_lookup(rooms, room); - - if (chat_room != NULL) { - char *old_nick = g_hash_table_lookup(chat_room->nick_changes, nick); - char *old_nick_cpy; - - if (old_nick != NULL) { - old_nick_cpy = strdup(old_nick); - g_hash_table_remove(chat_room->nick_changes, nick); - - return old_nick_cpy; - } - } - - return NULL; -} - static void -_room_free(muc_room *room) +_free_room(muc_room *room) { if (room != NULL) { if (room->room != NULL) { diff --git a/src/muc.h b/src/muc.h index 8a557ea3..f4a15c9a 100644 --- a/src/muc.h +++ b/src/muc.h @@ -27,33 +27,37 @@ #include "prof_autocomplete.h" -void room_join(const char * const room, const char * const nick); -void room_change_nick(const char * const room, const char * const nick); -void room_leave(const char * const room); -gboolean room_is_active(const char * const full_room_jid); -char * room_get_nick_for_room(const char * const room); +void muc_join_room(const char * const room, const char * const nick); +void muc_leave_room(const char * const room); +gboolean muc_room_is_active(const char * const full_room_jid); +GList* muc_get_active_room_list(void); +char * muc_get_room_nick(const char * const room); + +void muc_set_room_pending_nick_change(const char * const room); +gboolean muc_is_room_pending_nick_change(const char * const room); +void muc_complete_room_nick_change(const char * const room, + const char * const nick); + +gboolean muc_add_to_roster(const char * const room, const char * const nick, + const char * const show, const char * const status); +void muc_remove_from_roster(const char * const room, const char * const nick); +GList * muc_get_roster(const char * const room); +PAutocomplete muc_get_roster_ac(const char * const room); +gboolean muc_nick_in_roster(const char * const room, const char * const nick); +void muc_set_roster_received(const char * const room); +gboolean muc_get_roster_received(const char * const room); + +void muc_set_roster_pending_nick_change(const char * const room, + const char * const new_nick, const char * const old_nick); +char* muc_complete_roster_nick_change(const char * const room, + const char * const nick); + +gboolean room_from_jid_is_room(const char * const room_jid); +char * room_create_full_room_jid(const char * const room, + const char * const nick); char * room_get_room_from_full_jid(const char * const full_room_jid); char * room_get_nick_from_full_jid(const char * const full_room_jid); gboolean room_parse_room_jid(const char * const full_room_jid, char **room, char **nick); -gboolean room_add_to_roster(const char * const room, const char * const nick, - const char * const show, const char * const status); -void room_add_pending_nick_change(const char * const room, - const char * const new_nick, const char * const old_nick); -char* room_complete_pending_nick_change(const char * const room, - const char * const nick); -gboolean room_nick_in_roster(const char * const room, const char * const nick); -gboolean room_from_jid_is_room(const char * const room_jid); -PAutocomplete room_get_nick_ac(const char * const room); - -GList * room_get_roster(const char * const room); -void room_set_roster_received(const char * const room); -gboolean room_get_roster_received(const char * const room); -void room_remove_from_roster(const char * const room, const char * const nick); -char * room_create_full_room_jid(const char * const room, - const char * const nick); -void room_set_pending_nick_change(const char * const room); -gboolean room_is_pending_nick_change(const char * const room); -GList* room_get_rooms(void); #endif diff --git a/src/profanity.c b/src/profanity.c index 4ca9a52a..a16ea474 100644 --- a/src/profanity.c +++ b/src/profanity.c @@ -296,7 +296,7 @@ prof_handle_room_broadcast(const char *const room_jid, void prof_handle_room_roster_complete(const char * const room) { - room_set_roster_received(room); + muc_set_roster_received(room); win_show_room_roster(room); win_current_page_off(); } @@ -306,7 +306,7 @@ prof_handle_room_member_presence(const char * const room, const char * const nick, const char * const show, const char * const status) { - gboolean updated = room_add_to_roster(room, nick, show, status); + gboolean updated = muc_add_to_roster(room, nick, show, status); if (updated) { win_show_room_member_presence(room, nick, show, status); @@ -318,7 +318,7 @@ void prof_handle_room_member_online(const char * const room, const char * const nick, const char * const show, const char * const status) { - room_add_to_roster(room, nick, show, status); + muc_add_to_roster(room, nick, show, status); win_show_room_member_online(room, nick, show, status); win_current_page_off(); } @@ -327,7 +327,7 @@ void prof_handle_room_member_offline(const char * const room, const char * const nick, const char * const show, const char * const status) { - room_remove_from_roster(room, nick); + muc_remove_from_roster(room, nick); win_show_room_member_offline(room, nick); win_current_page_off(); } @@ -335,7 +335,7 @@ prof_handle_room_member_offline(const char * const room, const char * const nick void prof_handle_leave_room(const char * const room) { - room_leave(room); + muc_leave_room(room); } void diff --git a/src/windows.c b/src/windows.c index 869d6cbb..aeba6cd4 100644 --- a/src/windows.c +++ b/src/windows.c @@ -752,7 +752,7 @@ win_show_outgoing_msg(const char * const from, const char * const to, // create new window if (win_index == NUM_WINS) { - if (room_is_active(to)) { + if (muc_room_is_active(to)) { win_index = _new_prof_win(to, WIN_PRIVATE); } else { win_index = _new_prof_win(to, WIN_CHAT); @@ -810,7 +810,7 @@ win_show_room_roster(const char * const room) int win_index = _find_prof_win_index(room); WINDOW *win = windows[win_index]->win; - GList *roster = room_get_roster(room); + GList *roster = muc_get_roster(room); if ((roster == NULL) || (g_list_length(roster) == 0)) { wattron(win, COLOUR_ROOMINFO); @@ -982,7 +982,7 @@ win_show_room_message(const char * const room_jid, const char * const nick, WINDOW *win = windows[win_index]->win; _win_show_time(win); - if (strcmp(nick, room_get_nick_for_room(room_jid)) != 0) { + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { if (strncmp(message, "/me ", 4) == 0) { wattron(win, COLOUR_THEM); wprintw(win, "*%s ", nick); @@ -1020,7 +1020,7 @@ win_show_room_message(const char * const room_jid, const char * const nick, dirty = TRUE; } - if (strcmp(nick, room_get_nick_for_room(room_jid)) != 0) { + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { if (prefs_get_flash()) { flash(); } @@ -1029,7 +1029,7 @@ win_show_room_message(const char * const room_jid, const char * const nick, windows[win_index]->unread++; } - if (strcmp(nick, room_get_nick_for_room(room_jid)) != 0) { + if (strcmp(nick, muc_get_room_nick(room_jid)) != 0) { if (prefs_get_beep()) { beep(); }