diff --git a/interface.c b/interface.c
index db43a1b..d952a11 100644
--- a/interface.c
+++ b/interface.c
@@ -42,6 +42,8 @@
 #include "structures.h"
 
 #include "mtproto-common.h"
+
+#define ALLOW_MULT 1
 char *default_prompt = "> ";
 
 int unread_messages;
@@ -493,13 +495,24 @@ char **complete_text (char *text, int start UU, int end UU) {
   return (char **) rl_completion_matches (text, command_generator);
 }
 
-void work_modifier (const char *s UU) {
+int offline_mode;
+int count = 1;
+void work_modifier (const char *s, int l) {
+  if (is_same_word (s, l, "[offline]")) {
+    offline_mode = 1;
+  }
+#ifdef ALLOW_MULT
+  if (sscanf (s, "[x%d]", &count) >= 1) {
+  }
+#endif
 }
 
 void interpreter (char *line UU) {
   line_ptr = line;
   assert (!in_readline);
   in_readline = 1;
+  offline_mode = 0;
+  count = 1;
   if (!line) { 
     in_readline = 0;
     return; 
@@ -514,12 +527,20 @@ void interpreter (char *line UU) {
     command = next_token (&l);
     if (!command) { in_readline = 0; return; }
     if (*command == '[' && command[l - 1] == ']') {
-      work_modifier (command);
+      work_modifier (command, l);
     } else {
       break;
     }
   }
 
+  int _;
+  char *save = line_ptr;
+  int ll = l;
+  char *cs = command;
+  for (_ = 0; _ < count; _ ++) {
+    line_ptr = save;
+    l = ll;
+    command = cs;
 #define IS_WORD(s) is_same_word (command, l, (s))
 #define RET in_readline = 0; return; 
 
@@ -970,6 +991,7 @@ void interpreter (char *line UU) {
   } else if (IS_WORD ("quit")) {
     exit (0);
   }
+  }
 #undef IS_WORD
 #undef RET
   update_prompt ();
diff --git a/queries.c b/queries.c
index 695cb25..85cec4a 100644
--- a/queries.c
+++ b/queries.c
@@ -50,6 +50,7 @@
 
 char *get_downloads_directory (void);
 int verbosity;
+extern int offline_mode;
 
 long long cur_uploading_bytes;
 long long cur_uploaded_bytes;
@@ -1080,7 +1081,7 @@ void do_get_local_history (peer_id_t id, int limit) {
 }
 
 void do_get_history (peer_id_t id, int limit) {
-  if (get_peer_type (id) == PEER_ENCR_CHAT) {
+  if (get_peer_type (id) == PEER_ENCR_CHAT || offline_mode) {
     do_get_local_history (id, limit);
     do_mark_read (id);
     return;
@@ -1609,8 +1610,7 @@ void do_rename_chat (peer_id_t id, char *name) {
 /* }}} */
 
 /* {{{ Chat info */
-int chat_info_on_answer (struct query *q UU) {
-  struct chat *C = fetch_alloc_chat_full ();
+void print_chat_info (struct chat *C) {
   peer_t *U = (void *)C;
   print_start ();
   push_color (COLOR_YELLOW);
@@ -1632,6 +1632,11 @@ int chat_info_on_answer (struct query *q UU) {
   }
   pop_color ();
   print_end ();
+}
+
+int chat_info_on_answer (struct query *q UU) {
+  struct chat *C = fetch_alloc_chat_full ();
+  print_chat_info (C);
   return 0;
 }
 
@@ -1640,6 +1645,15 @@ struct query_methods chat_info_methods = {
 };
 
 void do_get_chat_info (peer_id_t id) {
+  if (offline_mode) {
+    peer_t *C = user_chat_get (id);
+    if (!C) {
+      rprintf ("No such chat\n");
+    } else {
+      print_chat_info (&C->chat);
+    }
+    return;
+  }
   clear_packet ();
   out_int (CODE_messages_get_full_chat);
   assert (get_peer_type (id) == PEER_CHAT);
@@ -1649,8 +1663,8 @@ void do_get_chat_info (peer_id_t id) {
 /* }}} */
 
 /* {{{ User info */
-int user_info_on_answer (struct query *q UU) {
-  struct user *U = fetch_alloc_user_full ();
+
+void print_user_info (struct user *U) {
   peer_t *C = (void *)U;
   print_start ();
   push_color (COLOR_YELLOW);
@@ -1668,6 +1682,11 @@ int user_info_on_answer (struct query *q UU) {
   }
   pop_color ();
   print_end ();
+}
+
+int user_info_on_answer (struct query *q UU) {
+  struct user *U = fetch_alloc_user_full ();
+  print_user_info (U);
   return 0;
 }
 
@@ -1676,6 +1695,15 @@ struct query_methods user_info_methods = {
 };
 
 void do_get_user_info (peer_id_t id) {
+  if (offline_mode) {
+    peer_t *C = user_chat_get (id);
+    if (!C) {
+      rprintf ("No such user\n");
+    } else {
+      print_user_info (&C->user);
+    }
+    return;
+  }
   clear_packet ();
   out_int (CODE_users_get_full_user);
   assert (get_peer_type (id) == PEER_USER);
diff --git a/structures.c b/structures.c
index a3cba31..56ff4ba 100644
--- a/structures.c
+++ b/structures.c
@@ -135,6 +135,7 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha
     s++;
   }
   s = buf;
+  int fl = strlen (s);
   int cc = 0;
   while (1) {
     int ok = 1;
@@ -149,17 +150,15 @@ char *create_print_name (peer_id_t id, const char *a1, const char *a2, const cha
       break;
     }
     cc ++;
-    assert (cc <= 99);
+    assert (cc <= 9999);
     if (cc == 1) {
       int l = strlen (s);
       s[l + 2] = 0;
       s[l] = '#';
       s[l + 1] = '1';
-    } else if (cc == 10) {
-      int l = strlen (s);
-      s[l + 1] = 0;
-      s[l] = '0';
-      s[l - 1] = '1';
+    } else if (cc == 10 || cc == 100 || cc == 1000) {
+//      int l = strlen (s);
+      sprintf (s + fl, "#%d", cc);
     } else {
       int l = strlen (s);
       s[l - 1] ++;
@@ -548,7 +547,7 @@ void fetch_chat_full (struct chat *C) {
     users_num = fetch_int ();
     users = malloc (sizeof (struct chat_user) * users_num);
     int i;
-    for (i = 0; i < C->users_num; i++) {
+    for (i = 0; i < users_num; i++) {
       assert (fetch_int () == (int)CODE_chat_participant);
       users[i].user_id = fetch_int ();
       users[i].inviter_id = fetch_int ();