Mercurial > hg
annotate mcabber/src/screen.c @ 328:83d129adde03
Add set_current_buddy() function, to reduce code duplication
author | Mikael Berthe <mikael@lilotux.net> |
---|---|
date | Sun, 17 Jul 2005 19:06:32 +0100 |
parents | ff6fb51bfd78 |
children | 7c53bf62a2a2 |
rev | line source |
---|---|
307 | 1 /* |
2 * screen.c -- UI stuff | |
3 * | |
4 * Copyright (C) 2005 Mikael Berthe <bmikael@lists.lilotux.net> | |
5 * Parts of this file come from the Cabber project <cabber@ajmacias.com> | |
6 * | |
7 * This program is free software; you can redistribute it and/or modify | |
8 * it under the terms of the GNU General Public License as published by | |
9 * the Free Software Foundation; either version 2 of the License, or (at | |
10 * your option) any later version. | |
11 * | |
12 * This program is distributed in the hope that it will be useful, but | |
13 * WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | |
15 * General Public License for more details. | |
16 * | |
17 * You should have received a copy of the GNU General Public License | |
18 * along with this program; if not, write to the Free Software | |
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 | |
20 * USA | |
21 */ | |
22 | |
24 | 23 #include <stdio.h> |
24 #include <stdlib.h> | |
25 #include <string.h> | |
26 #include <ncurses.h> | |
27 #include <panel.h> | |
28 #include <time.h> | |
29 #include <ctype.h> | |
30 #include <locale.h> | |
232 | 31 #include <langinfo.h> |
24 | 32 |
33 #include "screen.h" | |
81 | 34 #include "hbuf.h" |
47 | 35 #include "commands.h" |
95 | 36 #include "compl.h" |
81 | 37 #include "roster.h" |
180 | 38 #include "histolog.h" |
279
f5dd437c057b
Rewrite the settings system
Mikael Berthe <mikael@lilotux.net>
parents:
276
diff
changeset
|
39 #include "settings.h" |
81 | 40 #include "utils.h" |
24 | 41 #include "list.h" |
42 | |
43 #define window_entry(n) list_entry(n, window_entry_t, list) | |
44 | |
151 | 45 inline void check_offset(int); |
46 | |
24 | 47 LIST_HEAD(window_list); |
48 | |
49 typedef struct _window_entry_t { | |
50 WINDOW *win; | |
108 | 51 PANEL *panel; |
52 char *name; | |
53 GList *hbuf; | |
181 | 54 GList *top; // If top is NULL, we'll display the last lines |
55 char cleared; // For ex, user has issued a /clear command... | |
24 | 56 struct list_head list; |
57 } window_entry_t; | |
58 | |
59 | |
60 static WINDOW *rosterWnd, *chatWnd, *inputWnd; | |
61 static WINDOW *logWnd, *logWnd_border; | |
62 static PANEL *rosterPanel, *chatPanel, *inputPanel; | |
63 static PANEL *logPanel, *logPanel_border; | |
64 static int maxY, maxX; | |
65 static window_entry_t *currentWindow; | |
66 | |
67 static int chatmode; | |
238 | 68 static int multimode; |
69 static char *multiline; | |
30 | 70 int update_roster; |
232 | 71 int utf8_mode = 0; |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
72 static bool Autoaway; |
24 | 73 |
174 | 74 static char inputLine[INPUTLINE_LENGTH+1]; |
75 static char *ptr_inputline; | |
76 static short int inputline_offset; | |
77 static int completion_started; | |
173 | 78 static GList *cmdhisto; |
79 static GList *cmdhisto_cur; | |
174 | 80 static char cmdhisto_backup[INPUTLINE_LENGTH+1]; |
24 | 81 |
82 | |
99 | 83 /* Functions */ |
24 | 84 |
74 | 85 int scr_WindowWidth(WINDOW * win) |
24 | 86 { |
87 int x, y; | |
88 getmaxyx(win, y, x); | |
89 return x; | |
90 } | |
91 | |
74 | 92 void scr_clear_box(WINDOW *win, int y, int x, int height, int width, int Color) |
93 { | |
94 int i, j; | |
95 | |
96 wattrset(win, COLOR_PAIR(Color)); | |
97 for (i = 0; i < height; i++) { | |
98 wmove(win, y + i, x); | |
99 for (j = 0; j < width; j++) | |
100 wprintw(win, " "); | |
101 } | |
102 } | |
103 | |
24 | 104 void scr_draw_box(WINDOW * win, int y, int x, int height, int width, |
105 int Color, chtype box, chtype border) | |
106 { | |
107 int i, j; | |
108 | |
109 wattrset(win, COLOR_PAIR(Color)); | |
110 for (i = 0; i < height; i++) { | |
111 wmove(win, y + i, x); | |
112 for (j = 0; j < width; j++) | |
113 if (!i && !j) | |
114 waddch(win, border | ACS_ULCORNER); | |
115 else if (i == height - 1 && !j) | |
116 waddch(win, border | ACS_LLCORNER); | |
117 else if (!i && j == width - 1) | |
118 waddch(win, box | ACS_URCORNER); | |
119 else if (i == height - 1 && j == width - 1) | |
120 waddch(win, box | ACS_LRCORNER); | |
121 else if (!i) | |
122 waddch(win, border | ACS_HLINE); | |
123 else if (i == height - 1) | |
124 waddch(win, box | ACS_HLINE); | |
125 else if (!j) | |
126 waddch(win, border | ACS_VLINE); | |
127 else if (j == width - 1) | |
128 waddch(win, box | ACS_VLINE); | |
129 else | |
130 waddch(win, box | ' '); | |
131 } | |
132 } | |
133 | |
281
f562b9af2de7
Add "const" specifier in prototypes
Mikael Berthe <mikael@lilotux.net>
parents:
279
diff
changeset
|
134 int FindColor(const char *name) |
24 | 135 { |
136 if (!strcmp(name, "default")) | |
137 return -1; | |
138 if (!strcmp(name, "black")) | |
139 return COLOR_BLACK; | |
140 if (!strcmp(name, "red")) | |
141 return COLOR_RED; | |
142 if (!strcmp(name, "green")) | |
143 return COLOR_GREEN; | |
144 if (!strcmp(name, "yellow")) | |
145 return COLOR_YELLOW; | |
146 if (!strcmp(name, "blue")) | |
147 return COLOR_BLUE; | |
148 if (!strcmp(name, "magenta")) | |
149 return COLOR_MAGENTA; | |
150 if (!strcmp(name, "cyan")) | |
151 return COLOR_CYAN; | |
152 if (!strcmp(name, "white")) | |
153 return COLOR_WHITE; | |
154 | |
155 return -1; | |
156 } | |
157 | |
158 void ParseColors(void) | |
159 { | |
281
f562b9af2de7
Add "const" specifier in prototypes
Mikael Berthe <mikael@lilotux.net>
parents:
279
diff
changeset
|
160 const char *colors[8] = { |
24 | 161 "", "", |
267 | 162 "general", |
139 | 163 "newmsg", |
267 | 164 "rosterselect", |
165 "rosternormal", | |
24 | 166 NULL |
167 }; | |
168 | |
169 char *tmp = malloc(1024); | |
281
f562b9af2de7
Add "const" specifier in prototypes
Mikael Berthe <mikael@lilotux.net>
parents:
279
diff
changeset
|
170 const char *color; |
f562b9af2de7
Add "const" specifier in prototypes
Mikael Berthe <mikael@lilotux.net>
parents:
279
diff
changeset
|
171 const char *background = settings_opt_get("color_background"); |
f562b9af2de7
Add "const" specifier in prototypes
Mikael Berthe <mikael@lilotux.net>
parents:
279
diff
changeset
|
172 const char *backselected = settings_opt_get("color_backselected"); |
24 | 173 int i = 0; |
174 | |
267 | 175 // Default values |
176 if (!background) background = "blue"; | |
177 if (!backselected) backselected = "cyan"; | |
178 | |
24 | 179 while (colors[i]) { |
180 sprintf(tmp, "color_%s", colors[i]); | |
279
f5dd437c057b
Rewrite the settings system
Mikael Berthe <mikael@lilotux.net>
parents:
276
diff
changeset
|
181 color = settings_opt_get(tmp); |
24 | 182 |
183 switch (i + 1) { | |
184 case 1: | |
185 init_pair(1, COLOR_BLACK, COLOR_WHITE); | |
186 break; | |
187 case 2: | |
188 init_pair(2, COLOR_WHITE, COLOR_BLACK); | |
189 break; | |
190 case 3: | |
267 | 191 init_pair(3, ((color) ? FindColor(color) : COLOR_WHITE), |
192 FindColor(background)); | |
24 | 193 break; |
194 case 4: | |
267 | 195 init_pair(4, ((color) ? FindColor(color) : COLOR_RED), |
196 FindColor(background)); | |
24 | 197 break; |
198 case 5: | |
267 | 199 init_pair(5, ((color) ? FindColor(color) : COLOR_BLACK), |
200 FindColor(backselected)); | |
24 | 201 break; |
202 case 6: | |
267 | 203 init_pair(6, ((color) ? FindColor(color) : COLOR_MAGENTA), |
204 FindColor(background)); | |
24 | 205 break; |
206 } | |
207 i++; | |
208 } | |
209 } | |
210 | |
211 | |
151 | 212 window_entry_t *scr_CreateBuddyPanel(const char *title, int dont_show) |
24 | 213 { |
151 | 214 int x; |
215 int y; | |
216 int lines; | |
217 int cols; | |
153 | 218 window_entry_t *tmp; |
219 | |
220 do { | |
221 tmp = calloc(1, sizeof(window_entry_t)); | |
222 } while (!tmp); | |
24 | 223 |
151 | 224 // Dimensions |
225 x = ROSTER_WIDTH; | |
226 y = 0; | |
227 lines = CHAT_WIN_HEIGHT; | |
228 cols = maxX - ROSTER_WIDTH; | |
229 | |
24 | 230 tmp->win = newwin(lines, cols, y, x); |
154 | 231 while (!tmp->win) { |
232 usleep(250); | |
233 tmp->win = newwin(lines, cols, y, x); | |
234 } | |
168 | 235 wbkgd(tmp->win, COLOR_PAIR(COLOR_GENERAL)); |
24 | 236 tmp->panel = new_panel(tmp->win); |
153 | 237 tmp->name = (char *) calloc(1, 96); |
238 strncpy(tmp->name, title, 96); | |
24 | 239 |
143 | 240 if (!dont_show) { |
24 | 241 currentWindow = tmp; |
242 } else { | |
243 if (currentWindow) | |
244 top_panel(currentWindow->panel); | |
245 else | |
246 top_panel(chatPanel); | |
247 } | |
143 | 248 update_panels(); |
24 | 249 |
181 | 250 // Load buddy history from file (if enabled) |
185 | 251 hlog_read_history(title, &tmp->hbuf, maxX - ROSTER_WIDTH - PREFIX_WIDTH); |
181 | 252 |
24 | 253 list_add_tail(&tmp->list, &window_list); |
254 | |
255 return tmp; | |
256 } | |
257 | |
50 | 258 window_entry_t *scr_SearchWindow(const char *winId) |
24 | 259 { |
260 struct list_head *pos, *n; | |
261 window_entry_t *search_entry = NULL; | |
262 | |
263 list_for_each_safe(pos, n, &window_list) { | |
264 search_entry = window_entry(pos); | |
265 if (search_entry->name) { | |
266 if (!strcasecmp(search_entry->name, winId)) { | |
267 return search_entry; | |
268 } | |
269 } | |
270 } | |
271 return NULL; | |
272 } | |
273 | |
143 | 274 // scr_UpdateWindow() |
275 // (Re-)Display the given chat window. | |
74 | 276 void scr_UpdateWindow(window_entry_t *win_entry) |
277 { | |
278 int n; | |
279 int width; | |
184 | 280 hbb_line **lines, *line; |
74 | 281 GList *hbuf_head; |
184 | 282 char date[32]; |
74 | 283 |
108 | 284 width = scr_WindowWidth(win_entry->win); |
285 | |
286 // Should the window be empty? | |
287 if (win_entry->cleared) { | |
168 | 288 werase(win_entry->win); |
108 | 289 return; |
290 } | |
291 | |
105 | 292 // win_entry->top is the top message of the screen. If it set to NULL, we |
293 // are displaying the last messages. | |
294 | |
74 | 295 // We will show the last CHAT_WIN_HEIGHT lines. |
296 // Let's find out where it begins. | |
105 | 297 if (!win_entry->top || |
298 (g_list_position(g_list_first(win_entry->hbuf), win_entry->top) == -1)) { | |
299 // Move up CHAT_WIN_HEIGHT lines | |
300 win_entry->hbuf = g_list_last(win_entry->hbuf); | |
301 hbuf_head = win_entry->hbuf; | |
302 win_entry->top = NULL; // (Just to make sure) | |
303 n = 0; | |
304 while (hbuf_head && (n < CHAT_WIN_HEIGHT-1) && g_list_previous(hbuf_head)) { | |
305 hbuf_head = g_list_previous(hbuf_head); | |
306 n++; | |
307 } | |
308 } else | |
309 hbuf_head = win_entry->top; | |
74 | 310 |
311 // Get the last CHAT_WIN_HEIGHT lines. | |
312 lines = hbuf_get_lines(hbuf_head, CHAT_WIN_HEIGHT); | |
313 | |
314 // Display these lines | |
315 for (n = 0; n < CHAT_WIN_HEIGHT; n++) { | |
168 | 316 wmove(win_entry->win, n, 0); |
184 | 317 line = *(lines+n); |
185 | 318 // NOTE: update PREFIX_WIDTH if you change the date format!! |
319 // You need to set it to the whole prefix length + 1 | |
184 | 320 if (line) { |
321 if (line->timestamp) { | |
185 | 322 strftime(date, 35, "%m-%d %H:%M", localtime(&line->timestamp)); |
184 | 323 } else |
185 | 324 strcpy(date, " "); |
197 | 325 if (line->flags & HBB_PREFIX_INFO) { |
326 char dir = '*'; | |
327 if (line->flags & HBB_PREFIX_IN) | |
328 dir = '<'; | |
329 else if (line->flags & HBB_PREFIX_OUT) | |
330 dir = '>'; | |
331 wprintw(win_entry->win, "%.11s *%c* ", date, dir); | |
325
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
332 } else if (line->flags & HBB_PREFIX_ERR) { |
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
333 char dir = '#'; |
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
334 if (line->flags & HBB_PREFIX_IN) |
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
335 dir = '<'; |
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
336 else if (line->flags & HBB_PREFIX_OUT) |
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
337 dir = '>'; |
ff6fb51bfd78
Handle "error" message type
Mikael Berthe <mikael@lilotux.net>
parents:
322
diff
changeset
|
338 wprintw(win_entry->win, "%.11s #%c# ", date, dir); |
197 | 339 } else if (line->flags & HBB_PREFIX_IN) |
185 | 340 wprintw(win_entry->win, "%.11s <== ", date); |
184 | 341 else if (line->flags & HBB_PREFIX_OUT) |
185 | 342 wprintw(win_entry->win, "%.11s --> ", date); |
75 | 343 else { |
185 | 344 wprintw(win_entry->win, "%.11s ", date); |
75 | 345 } |
184 | 346 wprintw(win_entry->win, "%s", line->text); // line |
168 | 347 wclrtoeol(win_entry->win); |
184 | 348 g_free(line->text); |
168 | 349 } else { |
350 wclrtobot(win_entry->win); | |
351 break; | |
75 | 352 } |
74 | 353 } |
354 g_free(lines); | |
355 } | |
356 | |
143 | 357 // scr_ShowWindow() |
358 // Display the chat window with the given identifier. | |
50 | 359 void scr_ShowWindow(const char *winId) |
24 | 360 { |
74 | 361 window_entry_t *win_entry = scr_SearchWindow(winId); |
362 | |
181 | 363 if (!win_entry) |
180 | 364 win_entry = scr_CreateBuddyPanel(winId, FALSE); |
74 | 365 |
180 | 366 top_panel(win_entry->panel); |
367 currentWindow = win_entry; | |
368 chatmode = TRUE; | |
369 roster_msg_setflag(winId, FALSE); | |
370 roster_setflags(winId, ROSTER_FLAG_LOCK, TRUE); | |
371 update_roster = TRUE; | |
74 | 372 |
180 | 373 // Refresh the window |
374 scr_UpdateWindow(win_entry); | |
375 | |
376 // Finished :) | |
377 update_panels(); | |
142 | 378 |
379 top_panel(inputPanel); | |
24 | 380 } |
381 | |
143 | 382 // scr_ShowBuddyWindow() |
383 // Display the chat window buffer for the current buddy. | |
24 | 384 void scr_ShowBuddyWindow(void) |
385 { | |
105 | 386 const gchar *jid; |
140 | 387 |
105 | 388 if (!current_buddy) |
140 | 389 jid = NULL; |
390 else | |
391 jid = CURRENT_JID; | |
392 | |
393 if (!jid) { | |
394 top_panel(chatPanel); | |
143 | 395 top_panel(inputPanel); |
140 | 396 currentWindow = NULL; |
105 | 397 return; |
140 | 398 } |
399 | |
105 | 400 scr_ShowWindow(jid); |
24 | 401 } |
402 | |
403 | |
143 | 404 // scr_WriteInWindow() |
405 // Write some text in the winId window (this usually is a jid). | |
406 // Lines are splitted when they are too long to fit in the chat window. | |
407 // If this window doesn't exist, it is created. | |
184 | 408 void scr_WriteInWindow(const char *winId, const char *text, time_t timestamp, |
409 unsigned int prefix_flags, int force_show) | |
24 | 410 { |
74 | 411 window_entry_t *win_entry; |
24 | 412 int dont_show = FALSE; |
413 | |
74 | 414 // Look for the window entry. |
415 win_entry = scr_SearchWindow(winId); | |
416 | |
417 // Do we have to really show the window? | |
24 | 418 if (!chatmode) |
419 dont_show = TRUE; | |
74 | 420 else if ((!force_show) && ((!currentWindow || (currentWindow != win_entry)))) |
24 | 421 dont_show = TRUE; |
422 | |
74 | 423 // If the window entry doesn't exist yet, let's create it. |
424 if (win_entry == NULL) { | |
151 | 425 win_entry = scr_CreateBuddyPanel(winId, dont_show); |
24 | 426 } |
427 | |
220 | 428 // The message must be displayed -> update top pointer |
429 if (win_entry->cleared) | |
430 win_entry->top = g_list_last(win_entry->hbuf); | |
431 | |
184 | 432 hbuf_add_line(&win_entry->hbuf, text, timestamp, prefix_flags, |
185 | 433 maxX - ROSTER_WIDTH - PREFIX_WIDTH); |
74 | 434 |
108 | 435 if (win_entry->cleared) { |
220 | 436 win_entry->cleared = FALSE; |
437 if (g_list_next(win_entry->top)) | |
438 win_entry->top = g_list_next(win_entry->top); | |
439 } | |
440 | |
441 // Make sure the last line appears in the window; update top if necessary | |
442 if (win_entry->top) { | |
443 int dist; | |
444 GList *first = g_list_first(win_entry->hbuf); | |
445 dist = g_list_position(first, g_list_last(win_entry->hbuf)) - | |
446 g_list_position(first, win_entry->top); | |
447 if (dist >= CHAT_WIN_HEIGHT) | |
448 win_entry->top = NULL; | |
108 | 449 } |
450 | |
24 | 451 if (!dont_show) { |
74 | 452 // Show and refresh the window |
453 top_panel(win_entry->panel); | |
454 scr_UpdateWindow(win_entry); | |
142 | 455 top_panel(inputPanel); |
24 | 456 update_panels(); |
457 doupdate(); | |
458 } else { | |
148 | 459 roster_msg_setflag(winId, TRUE); |
30 | 460 update_roster = TRUE; |
24 | 461 } |
462 } | |
463 | |
464 void scr_InitCurses(void) | |
465 { | |
466 initscr(); | |
467 noecho(); | |
468 raw(); | |
35 | 469 halfdelay(5); |
24 | 470 start_color(); |
471 use_default_colors(); | |
472 | |
473 ParseColors(); | |
474 | |
475 getmaxyx(stdscr, maxY, maxX); | |
167 | 476 if (maxY < LOG_WIN_HEIGHT+2) |
477 maxY = LOG_WIN_HEIGHT+2; | |
24 | 478 inputLine[0] = 0; |
479 ptr_inputline = inputLine; | |
480 | |
35 | 481 setlocale(LC_CTYPE, ""); |
232 | 482 utf8_mode = (strcmp(nl_langinfo(CODESET), "UTF-8") == 0); |
24 | 483 |
484 return; | |
485 } | |
486 | |
81 | 487 void scr_TerminateCurses(void) |
488 { | |
489 clear(); | |
490 refresh(); | |
491 endwin(); | |
492 return; | |
493 } | |
494 | |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
495 void inline set_autoaway(bool setaway) |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
496 { |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
497 static enum imstatus oldstatus; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
498 Autoaway = setaway; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
499 |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
500 if (setaway) { |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
501 const char *msg; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
502 oldstatus = jb_getstatus(); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
503 msg = settings_opt_get("message_autoaway"); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
504 if (!msg) msg = MSG_AUTOAWAY; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
505 jb_setstatus(away, msg); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
506 } else { |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
507 // Back |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
508 jb_setstatus(oldstatus, NULL); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
509 } |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
510 } |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
511 |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
512 // Check if we should enter/leave automatic away status |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
513 void scr_CheckAutoAway(bool activity) |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
514 { |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
515 static time_t LastActivity; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
516 enum imstatus cur_st; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
517 unsigned int autoaway_timeout = settings_opt_get_int("autoaway"); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
518 |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
519 if (Autoaway && activity) set_autoaway(FALSE); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
520 if (!autoaway_timeout) return; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
521 if (!LastActivity || activity) time(&LastActivity); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
522 |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
523 cur_st = jb_getstatus(); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
524 // Auto-away is disabled for the following states |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
525 if ((cur_st == away) || (cur_st == notavail) || (cur_st == invisible)) |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
526 return; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
527 |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
528 if (!activity) { |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
529 time_t now; |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
530 time(&now); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
531 if (!Autoaway && (now > LastActivity + autoaway_timeout)) |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
532 set_autoaway(TRUE); |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
533 } |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
534 } |
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
535 |
151 | 536 // scr_DrawMainWindow() |
157 | 537 // Set fullinit to TRUE to also create panels. Set it to FALSE for a resize. |
151 | 538 // |
539 // I think it could be improved a _lot_ but I'm really not an ncurses | |
540 // expert... :-\ Mikael. | |
541 // | |
542 void scr_DrawMainWindow(unsigned int fullinit) | |
24 | 543 { |
157 | 544 if (fullinit) { |
545 /* Create windows */ | |
546 rosterWnd = newwin(CHAT_WIN_HEIGHT, ROSTER_WIDTH, 0, 0); | |
547 chatWnd = newwin(CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH, 0, ROSTER_WIDTH); | |
548 logWnd_border = newwin(LOG_WIN_HEIGHT, maxX, CHAT_WIN_HEIGHT, 0); | |
549 logWnd = newwin(LOG_WIN_HEIGHT-2, maxX-2, CHAT_WIN_HEIGHT+1, 1); | |
550 inputWnd = newwin(1, maxX, maxY-1, 0); | |
168 | 551 wbkgd(rosterWnd, COLOR_PAIR(COLOR_GENERAL)); |
552 wbkgd(chatWnd, COLOR_PAIR(COLOR_GENERAL)); | |
553 wbkgd(logWnd_border, COLOR_PAIR(COLOR_GENERAL)); | |
554 wbkgd(logWnd, COLOR_PAIR(COLOR_GENERAL)); | |
157 | 555 } else { |
556 /* Resize windows */ | |
557 wresize(rosterWnd, CHAT_WIN_HEIGHT, ROSTER_WIDTH); | |
558 wresize(chatWnd, CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH); | |
559 | |
560 wresize(logWnd_border, LOG_WIN_HEIGHT, maxX); | |
561 wresize(logWnd, LOG_WIN_HEIGHT-2, maxX-2); | |
562 mvwin(logWnd_border, CHAT_WIN_HEIGHT, 0); | |
563 mvwin(logWnd, CHAT_WIN_HEIGHT+1, 1); | |
564 | |
565 wresize(inputWnd, 1, maxX); | |
566 mvwin(inputWnd, maxY-1, 0); | |
168 | 567 |
568 werase(chatWnd); | |
157 | 569 } |
151 | 570 |
571 /* Draw/init windows */ | |
572 | |
74 | 573 mvwprintw(chatWnd, 0, 0, "This is the status window"); |
24 | 574 |
151 | 575 // - Draw/clear the log window |
24 | 576 scr_draw_box(logWnd_border, 0, 0, LOG_WIN_HEIGHT, maxX, COLOR_GENERAL, 0, 0); |
157 | 577 // Auto-scrolling in log window |
74 | 578 scrollok(logWnd, TRUE); |
24 | 579 |
580 | |
151 | 581 if (fullinit) { |
157 | 582 // Enable keypad (+ special keys) |
583 keypad(inputWnd, TRUE); | |
584 | |
151 | 585 // Create panels |
586 rosterPanel = new_panel(rosterWnd); | |
587 chatPanel = new_panel(chatWnd); | |
588 logPanel_border = new_panel(logWnd_border); | |
589 logPanel = new_panel(logWnd); | |
590 inputPanel = new_panel(inputWnd); | |
232 | 591 |
592 if (utf8_mode) | |
593 scr_LogPrint("WARNING: UTF-8 not yet supported!"); | |
157 | 594 } else { |
595 // Update panels | |
596 replace_panel(rosterPanel, rosterWnd); | |
597 replace_panel(chatPanel, chatWnd); | |
598 replace_panel(logPanel, logWnd); | |
599 replace_panel(logPanel_border, logWnd_border); | |
600 replace_panel(inputPanel, inputWnd); | |
151 | 601 } |
602 | |
603 // We'll need to redraw the roster | |
149 | 604 update_roster = TRUE; |
24 | 605 return; |
606 } | |
607 | |
151 | 608 // scr_Resize() |
609 // Function called when the window is resized. | |
157 | 610 // - Resize windows |
151 | 611 // - Rewrap lines in each buddy buffer |
612 void scr_Resize() | |
613 { | |
614 struct list_head *pos, *n; | |
615 window_entry_t *search_entry; | |
616 int x, y, lines, cols; | |
617 | |
618 // First, update the global variables | |
619 getmaxyx(stdscr, maxY, maxX); | |
167 | 620 if (maxY < LOG_WIN_HEIGHT+2) |
621 maxY = LOG_WIN_HEIGHT+2; | |
151 | 622 // Make sure the cursor stays inside the window |
623 check_offset(0); | |
624 | |
157 | 625 // Resize windows and update panels |
151 | 626 scr_DrawMainWindow(FALSE); |
627 | |
628 // Resize all buddy windows | |
629 x = ROSTER_WIDTH; | |
630 y = 0; | |
631 lines = CHAT_WIN_HEIGHT; | |
632 cols = maxX - ROSTER_WIDTH; | |
633 | |
634 list_for_each_safe(pos, n, &window_list) { | |
635 search_entry = window_entry(pos); | |
636 if (search_entry->win) { | |
189 | 637 GList *rescue_top; |
157 | 638 // Resize buddy window (no need to move it) |
639 wresize(search_entry->win, lines, cols); | |
168 | 640 werase(search_entry->win); |
151 | 641 // If a panel exists, replace the old window with the new |
642 if (search_entry->panel) { | |
643 replace_panel(search_entry->panel, search_entry->win); | |
644 } | |
645 // Redo line wrapping | |
189 | 646 rescue_top = hbuf_previous_persistent(search_entry->top); |
151 | 647 hbuf_rebuild(&search_entry->hbuf, |
185 | 648 maxX - ROSTER_WIDTH - PREFIX_WIDTH); |
189 | 649 if (g_list_position(g_list_first(search_entry->hbuf), search_entry->top) == -1) |
650 search_entry->top = rescue_top; | |
151 | 651 } |
652 } | |
653 | |
654 // Refresh current buddy window | |
157 | 655 if (chatmode) |
151 | 656 scr_ShowBuddyWindow(); |
657 } | |
658 | |
143 | 659 // scr_DrawRoster() |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
660 // Display the buddylist (not really the roster) on the screen |
81 | 661 void scr_DrawRoster(void) |
24 | 662 { |
81 | 663 static guint offset = 0; |
664 char name[ROSTER_WIDTH]; | |
665 int maxx, maxy; | |
666 GList *buddy; | |
667 int i, n; | |
668 int rOffset; | |
164 | 669 enum imstatus currentstatus = jb_getstatus(); |
81 | 670 |
123 | 671 // We can reset update_roster |
672 update_roster = FALSE; | |
673 | |
81 | 674 getmaxyx(rosterWnd, maxy, maxx); |
675 maxx --; // last char is for vertical border | |
676 name[ROSTER_WIDTH-7] = 0; | |
677 | |
678 // cleanup of roster window | |
168 | 679 werase(rosterWnd); |
680 // Redraw the vertical line (not very good...) | |
81 | 681 wattrset(rosterWnd, COLOR_PAIR(COLOR_GENERAL)); |
168 | 682 for (i=0 ; i < CHAT_WIN_HEIGHT ; i++) |
683 mvwaddch(rosterWnd, i, ROSTER_WIDTH-1, ACS_VLINE); | |
81 | 684 |
685 // Leave now if buddylist is empty | |
686 if (!buddylist) { | |
687 offset = 0; | |
123 | 688 update_panels(); |
689 doupdate(); | |
81 | 690 return; |
691 } | |
692 | |
84 | 693 // Update offset if necessary |
694 i = g_list_position(buddylist, current_buddy); | |
695 if (i == -1) { // This is bad | |
696 scr_LogPrint("Doh! Can't find current selected buddy!!"); | |
697 return; | |
698 } else if (i < offset) { | |
699 offset = i; | |
700 } else if (i+1 > offset + maxy) { | |
701 offset = i + 1 - maxy; | |
702 } | |
81 | 703 |
704 buddy = buddylist; | |
705 rOffset = offset; | |
706 | |
84 | 707 for (i=0; i<maxy && buddy; buddy = g_list_next(buddy)) { |
81 | 708 |
709 char status = '?'; | |
710 char pending = ' '; | |
711 enum imstatus budstate; | |
149 | 712 unsigned short ismsg = buddy_getflags(BUDDATA(buddy)) & ROSTER_FLAG_MSG; |
713 unsigned short isgrp = buddy_gettype(BUDDATA(buddy)) & ROSTER_TYPE_GROUP; | |
714 unsigned short ishid = buddy_getflags(BUDDATA(buddy)) & ROSTER_FLAG_HIDE; | |
81 | 715 |
716 if (rOffset > 0) { | |
717 rOffset--; | |
718 continue; | |
719 } | |
720 | |
149 | 721 // Display message notice if there is a message flag, but not |
722 // for unfolded groups. | |
723 if (ismsg && (!isgrp || ishid)) { | |
81 | 724 pending = '#'; |
725 } | |
726 | |
727 budstate = buddy_getstatus(BUDDATA(buddy)); | |
164 | 728 if (budstate >= 0 && budstate < imstatus_size && currentstatus != offline) |
81 | 729 status = imstatus2char[budstate]; |
730 if (buddy == current_buddy) { | |
731 wattrset(rosterWnd, COLOR_PAIR(COLOR_BD_DESSEL)); | |
732 // The 3 following lines aim to color the whole line | |
733 wmove(rosterWnd, i, 0); | |
734 for (n = 0; n < maxx; n++) | |
735 waddch(rosterWnd, ' '); | |
736 } else { | |
149 | 737 if (pending == '#') |
139 | 738 wattrset(rosterWnd, COLOR_PAIR(COLOR_NMSG)); |
739 else | |
740 wattrset(rosterWnd, COLOR_PAIR(COLOR_BD_DES)); | |
81 | 741 } |
742 | |
743 strncpy(name, buddy_getname(BUDDATA(buddy)), ROSTER_WIDTH-7); | |
149 | 744 if (isgrp) { |
133 | 745 char *sep; |
149 | 746 if (ishid) |
133 | 747 sep = "+++"; |
748 else | |
749 sep = "---"; | |
750 mvwprintw(rosterWnd, i, 0, " %c%s %s", pending, sep, name); | |
751 } | |
126 | 752 else |
753 mvwprintw(rosterWnd, i, 0, " %c[%c] %s", pending, status, name); | |
84 | 754 |
755 i++; | |
81 | 756 } |
757 | |
142 | 758 top_panel(inputPanel); |
81 | 759 update_panels(); |
760 doupdate(); | |
24 | 761 } |
762 | |
184 | 763 void scr_WriteMessage(const char *jid, const char *text, time_t timestamp, |
764 guint prefix_flags) | |
24 | 765 { |
184 | 766 if (!timestamp) timestamp = time(NULL); |
767 | |
768 scr_WriteInWindow(jid, text, timestamp, prefix_flags, FALSE); | |
47 | 769 } |
770 | |
190 | 771 // If prefix is NULL, HBB_PREFIX_IN is supposed. |
184 | 772 void scr_WriteIncomingMessage(const char *jidfrom, const char *text, |
190 | 773 time_t timestamp, guint prefix) |
47 | 774 { |
190 | 775 if (!prefix) prefix = HBB_PREFIX_IN; |
75 | 776 // FIXME expand tabs / filter out special chars... |
190 | 777 scr_WriteMessage(jidfrom, text, timestamp, prefix); |
24 | 778 update_panels(); |
779 doupdate(); | |
780 } | |
781 | |
50 | 782 void scr_WriteOutgoingMessage(const char *jidto, const char *text) |
47 | 783 { |
184 | 784 scr_WriteMessage(jidto, text, 0, HBB_PREFIX_OUT); |
47 | 785 scr_ShowWindow(jidto); |
786 } | |
787 | |
24 | 788 int scr_Getch(void) |
789 { | |
790 int ch; | |
791 ch = wgetch(inputWnd); | |
792 return ch; | |
793 } | |
794 | |
795 WINDOW *scr_GetRosterWindow(void) | |
796 { | |
797 return rosterWnd; | |
798 } | |
799 | |
800 WINDOW *scr_GetStatusWindow(void) | |
801 { | |
802 return chatWnd; | |
803 } | |
804 | |
805 WINDOW *scr_GetInputWindow(void) | |
806 { | |
807 return inputWnd; | |
808 } | |
809 | |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
810 // set_current_buddy(newbuddy) |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
811 // Set the current_buddy to newbuddy (if not NULL) |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
812 // Lock the newbuddy, and unlock the previous current_buddy |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
813 static void set_current_buddy(GList *newbuddy) |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
814 { |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
815 enum imstatus prev_st = imstatus_size; |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
816 /* prev_st initialized to imstatus_size, which is used as "undef" value. |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
817 * We are sure prev_st will get a different status value after the |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
818 * buddy_getstatus() call. |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
819 */ |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
820 |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
821 if (!current_buddy || !newbuddy) return; |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
822 |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
823 prev_st = buddy_getstatus(BUDDATA(current_buddy)); |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
824 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, FALSE); |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
825 current_buddy = newbuddy; |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
826 // Lock the buddy in the buddylist if we're in chat mode |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
827 if (chatmode) |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
828 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, TRUE); |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
829 // We should rebuild the buddylist but not everytime |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
830 // Here we check if we were locking a buddy who is actually offline, |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
831 // and hide_offline_buddies is TRUE. In which case we need to rebuild. |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
832 if (prev_st == offline && buddylist_get_hide_offline_buddies()) |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
833 buddylist_build(); |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
834 update_roster = TRUE; |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
835 } |
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
836 |
143 | 837 // scr_RosterTop() |
838 // Go to the first buddy in the buddylist | |
105 | 839 void scr_RosterTop(void) |
104 | 840 { |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
841 set_current_buddy(buddylist); |
104 | 842 if (chatmode) |
843 scr_ShowBuddyWindow(); | |
844 } | |
845 | |
143 | 846 // scr_RosterBottom() |
847 // Go to the last buddy in the buddylist | |
105 | 848 void scr_RosterBottom(void) |
104 | 849 { |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
850 set_current_buddy(g_list_last(buddylist)); |
104 | 851 if (chatmode) |
852 scr_ShowBuddyWindow(); | |
853 } | |
854 | |
143 | 855 // scr_RosterUp() |
856 // Go to the previous buddy in the buddylist | |
105 | 857 void scr_RosterUp(void) |
81 | 858 { |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
859 set_current_buddy(g_list_previous(current_buddy)); |
104 | 860 if (chatmode) |
861 scr_ShowBuddyWindow(); | |
81 | 862 } |
863 | |
143 | 864 // scr_RosterDown() |
865 // Go to the next buddy in the buddylist | |
105 | 866 void scr_RosterDown(void) |
81 | 867 { |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
868 set_current_buddy(g_list_next(current_buddy)); |
104 | 869 if (chatmode) |
870 scr_ShowBuddyWindow(); | |
81 | 871 } |
872 | |
265 | 873 // scr_RosterSearch(str) |
874 // Look forward for a buddy with jid/name containing str. | |
875 void scr_RosterSearch(char *str) | |
876 { | |
328
83d129adde03
Add set_current_buddy() function, to reduce code duplication
Mikael Berthe <mikael@lilotux.net>
parents:
325
diff
changeset
|
877 set_current_buddy(buddy_search(str)); |
265 | 878 if (chatmode) |
879 scr_ShowBuddyWindow(); | |
880 } | |
881 | |
236 | 882 // scr_RosterUnreadMessage(next) |
883 // Go to a new message. If next is not null, try to go to the next new | |
884 // message. If it is not possible or if next is NULL, go to the first new | |
885 // message from unread_list. | |
886 void scr_RosterUnreadMessage(int next) | |
887 { | |
888 enum imstatus prev_st = imstatus_size; // undef | |
889 | |
890 if (current_buddy) { | |
891 gpointer unread_ptr; | |
892 gpointer refbuddata; | |
893 gpointer ngroup; | |
894 GList *nbuddy; | |
895 | |
896 if (next) refbuddata = BUDDATA(current_buddy); | |
897 else refbuddata = NULL; | |
898 | |
899 unread_ptr = unread_msg(refbuddata); | |
900 if (!unread_ptr) return; | |
901 | |
902 // If buddy is in a folded group, we need to expand it | |
903 ngroup = buddy_getgroup(unread_ptr); | |
904 if (buddy_getflags(ngroup) & ROSTER_FLAG_HIDE) { | |
905 buddy_setflags(ngroup, ROSTER_FLAG_HIDE, FALSE); | |
906 buddylist_build(); | |
907 } | |
908 | |
909 nbuddy = g_list_find(buddylist, unread_ptr); | |
910 if (nbuddy) { | |
911 prev_st = buddy_getstatus(BUDDATA(current_buddy)); | |
912 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, FALSE); | |
913 current_buddy = nbuddy; | |
914 if (chatmode) | |
915 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, TRUE); | |
916 // We should rebuild the buddylist but not everytime | |
917 // Here we check if we were locking a buddy who is actually offline, | |
918 // and hide_offline_buddies is TRUE. In which case we need to rebuild. | |
919 if (prev_st == offline && buddylist_get_hide_offline_buddies()) | |
920 buddylist_build(); | |
921 update_roster = TRUE; | |
922 | |
923 if (chatmode) scr_ShowBuddyWindow(); | |
924 } else scr_LogPrint("Error: nbuddy == NULL"); | |
925 } | |
926 } | |
927 | |
143 | 928 // scr_ScrollUp() |
929 // Scroll up the current buddy window, half a screen. | |
105 | 930 void scr_ScrollUp(void) |
931 { | |
932 const gchar *jid; | |
933 window_entry_t *win_entry; | |
934 int n, nblines; | |
935 GList *hbuf_top; | |
936 | |
937 // Get win_entry | |
938 if (!current_buddy) | |
939 return; | |
940 jid = CURRENT_JID; | |
941 if (!jid) | |
942 return; | |
943 win_entry = scr_SearchWindow(jid); | |
944 if (!win_entry) | |
945 return; | |
946 | |
947 // Scroll up half a screen (or less) | |
948 nblines = CHAT_WIN_HEIGHT/2-1; | |
949 hbuf_top = win_entry->top; | |
950 if (!hbuf_top) { | |
951 hbuf_top = g_list_last(win_entry->hbuf); | |
109 | 952 if (!win_entry->cleared) |
953 nblines *= 3; | |
954 else | |
955 win_entry->cleared = FALSE; | |
105 | 956 } |
957 | |
958 n = 0; | |
959 while (hbuf_top && n < nblines && g_list_previous(hbuf_top)) { | |
960 hbuf_top = g_list_previous(hbuf_top); | |
961 n++; | |
962 } | |
963 win_entry->top = hbuf_top; | |
964 | |
965 // Refresh the window | |
966 scr_UpdateWindow(win_entry); | |
967 | |
968 // Finished :) | |
969 update_panels(); | |
970 doupdate(); | |
971 } | |
972 | |
143 | 973 // scr_ScrollDown() |
974 // Scroll down the current buddy window, half a screen. | |
105 | 975 void scr_ScrollDown(void) |
976 { | |
977 const gchar *jid; | |
978 window_entry_t *win_entry; | |
979 int n, nblines; | |
980 GList *hbuf_top; | |
981 | |
982 // Get win_entry | |
983 if (!current_buddy) | |
984 return; | |
985 jid = CURRENT_JID; | |
986 if (!jid) | |
987 return; | |
988 win_entry = scr_SearchWindow(jid); | |
989 if (!win_entry) | |
990 return; | |
991 | |
992 // Scroll down half a screen (or less) | |
993 nblines = CHAT_WIN_HEIGHT/2-1; | |
994 hbuf_top = win_entry->top; | |
995 | |
996 for (n=0 ; hbuf_top && n < nblines ; n++) | |
997 hbuf_top = g_list_next(hbuf_top); | |
998 win_entry->top = hbuf_top; | |
999 // Check if we are at the bottom | |
1000 for (n=0 ; hbuf_top && n < CHAT_WIN_HEIGHT-1 ; n++) | |
1001 hbuf_top = g_list_next(hbuf_top); | |
1002 if (!hbuf_top) | |
1003 win_entry->top = NULL; // End reached | |
1004 | |
1005 // Refresh the window | |
1006 scr_UpdateWindow(win_entry); | |
1007 | |
1008 // Finished :) | |
1009 update_panels(); | |
1010 doupdate(); | |
1011 } | |
1012 | |
143 | 1013 // scr_Clear() |
1014 // Clear the current buddy window (used for the /clear command) | |
108 | 1015 void scr_Clear(void) |
1016 { | |
1017 const gchar *jid; | |
1018 window_entry_t *win_entry; | |
1019 | |
1020 // Get win_entry | |
1021 if (!current_buddy) | |
1022 return; | |
1023 jid = CURRENT_JID; | |
1024 if (!jid) | |
1025 return; | |
1026 win_entry = scr_SearchWindow(jid); | |
1027 if (!win_entry) | |
1028 return; | |
1029 | |
1030 win_entry->cleared = TRUE; | |
109 | 1031 win_entry->top = NULL; |
108 | 1032 |
1033 // Refresh the window | |
1034 scr_UpdateWindow(win_entry); | |
1035 | |
1036 // Finished :) | |
1037 update_panels(); | |
1038 doupdate(); | |
1039 } | |
1040 | |
187 | 1041 // scr_BufferTop() |
1042 // Jump to the head of the current buddy window | |
1043 void scr_BufferTop(void) | |
1044 { | |
1045 const gchar *jid; | |
1046 window_entry_t *win_entry; | |
1047 | |
1048 // Get win_entry | |
1049 if (!current_buddy) return; | |
1050 jid = CURRENT_JID; | |
1051 if (!jid) return; | |
1052 win_entry = scr_SearchWindow(jid); | |
1053 | |
1054 if (!win_entry) return; | |
1055 | |
1056 win_entry->cleared = FALSE; | |
1057 win_entry->top = g_list_first(win_entry->hbuf); | |
1058 | |
1059 // Refresh the window | |
1060 scr_UpdateWindow(win_entry); | |
1061 | |
1062 // Finished :) | |
1063 update_panels(); | |
1064 doupdate(); | |
1065 } | |
1066 | |
1067 // scr_BufferBottom() | |
1068 // Jump to the end of the current buddy window | |
1069 void scr_BufferBottom(void) | |
1070 { | |
1071 const gchar *jid; | |
1072 window_entry_t *win_entry; | |
1073 | |
1074 // Get win_entry | |
1075 if (!current_buddy) return; | |
1076 jid = CURRENT_JID; | |
1077 if (!jid) return; | |
1078 win_entry = scr_SearchWindow(jid); | |
1079 | |
1080 if (!win_entry) return; | |
1081 | |
1082 win_entry->cleared = FALSE; | |
1083 win_entry->top = NULL; | |
1084 | |
1085 // Refresh the window | |
1086 scr_UpdateWindow(win_entry); | |
1087 | |
1088 // Finished :) | |
1089 update_panels(); | |
1090 doupdate(); | |
1091 } | |
1092 | |
44 | 1093 // scr_LogPrint(...) |
1094 // Display a message in the log window. | |
24 | 1095 void scr_LogPrint(const char *fmt, ...) |
1096 { | |
1097 time_t timestamp; | |
1098 char *buffer; | |
1099 va_list ap; | |
1100 | |
153 | 1101 do { |
157 | 1102 buffer = (char *) calloc(1, 1024); |
153 | 1103 } while (!buffer); |
24 | 1104 |
1105 timestamp = time(NULL); | |
1106 strftime(buffer, 64, "[%H:%M:%S] ", localtime(×tamp)); | |
1107 wprintw(logWnd, "\n%s", buffer); | |
1108 | |
1109 va_start(ap, fmt); | |
153 | 1110 vsnprintf(buffer, 1024, fmt, ap); |
24 | 1111 va_end(ap); |
1112 | |
1113 wprintw(logWnd, "%s", buffer); | |
1114 free(buffer); | |
1115 | |
1116 update_panels(); | |
1117 doupdate(); | |
1118 } | |
1119 | |
143 | 1120 // scr_set_chatmode() |
261 | 1121 // Public function to (un)set chatmode... |
129 | 1122 inline void scr_set_chatmode(int enable) |
1123 { | |
1124 chatmode = enable; | |
1125 } | |
1126 | |
238 | 1127 // scr_get_multimode() |
261 | 1128 // Public function to get multimode status... |
238 | 1129 inline int scr_get_multimode() |
1130 { | |
1131 return multimode; | |
1132 } | |
1133 | |
1134 // scr_set_multimode() | |
261 | 1135 // Public function to (un)set multimode... |
260
33e1a05864a6
Add "verbatim multi-line" mode, with commands disabled
mikael@frmp8452
parents:
252
diff
changeset
|
1136 // Convention: |
33e1a05864a6
Add "verbatim multi-line" mode, with commands disabled
mikael@frmp8452
parents:
252
diff
changeset
|
1137 // 0 = disabled / 1 = multimode / 2 = multimode verbatim (commands disabled) |
238 | 1138 inline void scr_set_multimode(int enable) |
1139 { | |
1140 if (multiline) { | |
1141 g_free(multiline); | |
1142 multiline = NULL; | |
1143 } | |
260
33e1a05864a6
Add "verbatim multi-line" mode, with commands disabled
mikael@frmp8452
parents:
252
diff
changeset
|
1144 multimode = enable; |
238 | 1145 } |
1146 | |
1147 // scr_get_multiline() | |
261 | 1148 // Public function to get the current multi-line. |
238 | 1149 inline const char *scr_get_multiline() |
1150 { | |
1151 if (multimode && multiline) | |
1152 return multiline; | |
1153 else | |
1154 return ""; | |
1155 } | |
1156 | |
1157 // scr_append_multiline(line) | |
1158 // Public function to append a line to the current multi-line message. | |
1159 // Skip empty leading lines. | |
1160 void scr_append_multiline(const char *line) | |
1161 { | |
1162 static int num; | |
1163 | |
1164 if (!multimode) { | |
1165 scr_LogPrint("Error: Not in multi-line message mode!"); | |
1166 return; | |
1167 } | |
1168 if (multiline) { | |
1169 int len = strlen(multiline)+strlen(line)+2; | |
252 | 1170 if (len >= HBB_BLOCKSIZE - 1) { |
238 | 1171 // We don't handle single messages with size > HBB_BLOCKSIZE |
1172 // (see hbuf) | |
1173 scr_LogPrint("Your multi-line message is too big, this line has " | |
1174 "not been added."); | |
1175 scr_LogPrint("Please send this part now..."); | |
1176 return; | |
1177 } | |
276
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1178 if (num >= MULTILINE_MAX_LINE_NUMBER) { |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1179 // We don't allow too many lines; however the maximum is arbitrary |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1180 // (It should be < 1000 yet) |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1181 scr_LogPrint("Your message has too many lines, this one has " |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1182 "not been added."); |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1183 scr_LogPrint("Please send this part now..."); |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1184 return; |
627925d885de
Limit the number of lines in multi-line messages
Mikael Berthe <mikael@lilotux.net>
parents:
271
diff
changeset
|
1185 } |
238 | 1186 multiline = g_renew(char, multiline, len); |
1187 strcat(multiline, "\n"); | |
1188 strcat(multiline, line); | |
1189 num++; | |
1190 } else { | |
1191 // First message line (we skip leading empty lines) | |
1192 num = 0; | |
1193 if (line[0]) { | |
1194 multiline = g_new(char, strlen(line)+1); | |
1195 strcpy(multiline, line); | |
1196 num++; | |
1197 } else | |
1198 return; | |
1199 } | |
1200 scr_LogPrint("Multi-line mode: line #%d added [%.25s...", num, line); | |
1201 } | |
1202 | |
173 | 1203 // scr_cmdhisto_addline() |
1204 // Add a line to the inputLine history | |
1205 inline void scr_cmdhisto_addline(char *line) | |
1206 { | |
1207 if (!line || !*line) return; | |
1208 | |
1209 cmdhisto = g_list_append(cmdhisto, g_strdup(line)); | |
1210 } | |
1211 | |
1212 // scr_cmdhisto_prev() | |
1213 // Look for previous line beginning w/ the given mask in the inputLine history | |
175 | 1214 // Returns NULL if none found |
173 | 1215 const char *scr_cmdhisto_prev(char *mask, guint len) |
1216 { | |
1217 GList *hl; | |
1218 if (!cmdhisto_cur) { | |
1219 hl = g_list_last(cmdhisto); | |
174 | 1220 if (hl) { // backup current line |
1221 strncpy(cmdhisto_backup, mask, INPUTLINE_LENGTH); | |
1222 } | |
173 | 1223 } else { |
1224 hl = g_list_previous(cmdhisto_cur); | |
1225 } | |
1226 while (hl) { | |
1227 if (!strncmp((char*)hl->data, mask, len)) { | |
1228 // Found a match | |
1229 cmdhisto_cur = hl; | |
1230 return (const char*)hl->data; | |
1231 } | |
1232 hl = g_list_previous(hl); | |
1233 } | |
1234 return NULL; | |
1235 } | |
1236 | |
1237 // scr_cmdhisto_next() | |
1238 // Look for next line beginning w/ the given mask in the inputLine history | |
175 | 1239 // Returns NULL if none found |
173 | 1240 const char *scr_cmdhisto_next(char *mask, guint len) |
1241 { | |
1242 GList *hl; | |
1243 if (!cmdhisto_cur) return NULL; | |
1244 hl = cmdhisto_cur; | |
1245 while ((hl = g_list_next(hl)) != NULL) | |
1246 if (!strncmp((char*)hl->data, mask, len)) { | |
1247 // Found a match | |
1248 cmdhisto_cur = hl; | |
1249 return (const char*)hl->data; | |
1250 } | |
175 | 1251 // If the "backuped" line matches, we'll use it |
1252 if (strncmp(cmdhisto_backup, mask, len)) return NULL; // No match | |
174 | 1253 cmdhisto_cur = NULL; |
1254 return cmdhisto_backup; | |
173 | 1255 } |
1256 | |
195 | 1257 // readline_transpose_chars() |
1258 // Drag the character before point forward over the character at | |
1259 // point, moving point forward as well. If point is at the end of | |
1260 // the line, then this transposes the two characters before point. | |
1261 void readline_transpose_chars() | |
1262 { | |
1263 char swp; | |
1264 | |
1265 if (ptr_inputline == inputLine) return; | |
1266 | |
1267 if (!*ptr_inputline) { // We're at EOL | |
1268 // If line is only 1 char long, nothing to do... | |
1269 if (ptr_inputline == inputLine+1) return; | |
1270 // Transpose the two previous characters | |
1271 swp = *(ptr_inputline-2); | |
1272 *(ptr_inputline-2) = *(ptr_inputline-1); | |
1273 *(ptr_inputline-1) = swp; | |
1274 } else { | |
196 | 1275 // Swap the two characters before the cursor and move right. |
195 | 1276 swp = *(ptr_inputline-1); |
1277 *(ptr_inputline-1) = *ptr_inputline; | |
1278 *ptr_inputline++ = swp; | |
1279 check_offset(1); | |
1280 } | |
1281 } | |
1282 | |
1283 // readline_backward_kill_word() | |
194 | 1284 // Kill the word before the cursor, in input line |
195 | 1285 void readline_backward_kill_word() |
194 | 1286 { |
1287 char *c, *old = ptr_inputline; | |
1288 int spaceallowed = 1; | |
1289 | |
1290 if (ptr_inputline == inputLine) return; | |
1291 | |
1292 for (c = ptr_inputline-1 ; c > inputLine ; c--) | |
1293 if (!isalnum(*c)) { | |
1294 if (*c == ' ') | |
1295 if (!spaceallowed) break; | |
1296 } else spaceallowed = 0; | |
1297 | |
1298 if (c != inputLine || *c != ' ') | |
1299 if ((c < ptr_inputline-1) && (!isalnum(*c))) | |
1300 c++; | |
1301 | |
1302 // Modify the line | |
1303 ptr_inputline = c; | |
1304 for (;;) { | |
1305 *c = *old++; | |
1306 if (!*c++) break; | |
1307 } | |
195 | 1308 check_offset(-1); |
194 | 1309 } |
1310 | |
98 | 1311 // which_row() |
1312 // Tells which row our cursor is in, in the command line. | |
1313 // -1 -> normal text | |
1314 // 0 -> command | |
1315 // 1 -> parameter 1 (etc.) | |
102 | 1316 // If > 0, then *p_row is set to the beginning of the row |
1317 int which_row(char **p_row) | |
98 | 1318 { |
1319 int row = -1; | |
1320 char *p; | |
1321 int quote = FALSE; | |
1322 | |
1323 // Not a command? | |
1324 if ((ptr_inputline == inputLine) || (inputLine[0] != '/')) | |
1325 return -1; | |
1326 | |
1327 // This is a command | |
1328 row = 0; | |
1329 for (p = inputLine ; p < ptr_inputline ; p++) { | |
1330 if (quote) { | |
1331 if (*p == '"' && *(p-1) != '\\') | |
1332 quote = FALSE; | |
1333 continue; | |
1334 } | |
1335 if (*p == '"' && *(p-1) != '\\') { | |
1336 quote = TRUE; | |
121 | 1337 } else if (*p == ' ') { |
1338 if (*(p-1) != ' ') | |
1339 row++; | |
102 | 1340 *p_row = p+1; |
1341 } | |
98 | 1342 } |
1343 return row; | |
1344 } | |
1345 | |
143 | 1346 // scr_insert_text() |
1347 // Insert the given text at the current cursor position. | |
1348 // The cursor is moved. We don't check if the cursor still is in the screen | |
1349 // after, the caller should do that. | |
98 | 1350 void scr_insert_text(const char *text) |
1351 { | |
1352 char tmpLine[INPUTLINE_LENGTH+1]; | |
1353 int len = strlen(text); | |
1354 // Check the line isn't too long | |
1355 if (strlen(inputLine) + len >= INPUTLINE_LENGTH) { | |
1356 scr_LogPrint("Cannot insert text, line too long."); | |
1357 return; | |
1358 } | |
1359 | |
1360 strcpy(tmpLine, ptr_inputline); | |
1361 strcpy(ptr_inputline, text); ptr_inputline += len; | |
1362 strcpy(ptr_inputline, tmpLine); | |
1363 } | |
1364 | |
143 | 1365 // scr_handle_tab() |
1366 // Function called when tab is pressed. | |
1367 // Initiate or continue a completion... | |
98 | 1368 void scr_handle_tab(void) |
1369 { | |
102 | 1370 int nrow; |
1371 char *row; | |
1372 const char *cchar; | |
103 | 1373 guint compl_categ; |
98 | 1374 |
102 | 1375 nrow = which_row(&row); |
98 | 1376 |
103 | 1377 // a) No completion if no leading slash ('cause not a command) |
1378 // b) We can't have more than 2 parameters (we use 2 flags) | |
1379 if (nrow < 0 || nrow > 2) return; | |
102 | 1380 |
103 | 1381 if (nrow == 0) { // Command completion |
1382 row = &inputLine[1]; | |
1383 compl_categ = COMPL_CMD; | |
1384 } else { // Other completion, depending on the command | |
285 | 1385 int alias = FALSE; |
1386 cmd *com; | |
1387 char *xpline = expandalias(inputLine); | |
1388 com = cmd_get(xpline); | |
1389 if (xpline != inputLine) { | |
1390 // This is an alias, so we can't complete rows > 0 | |
1391 alias = TRUE; | |
1392 g_free(xpline); | |
1393 } | |
1394 if ((!com && (!alias || !completion_started)) || !row) { | |
103 | 1395 scr_LogPrint("I cannot complete that..."); |
1396 return; | |
1397 } | |
285 | 1398 if (!alias) |
1399 compl_categ = com->completion_flags[nrow-1]; | |
1400 else | |
1401 compl_categ = 0; | |
103 | 1402 } |
1403 | |
1404 if (!completion_started) { | |
1405 GSList *list = compl_get_category_list(compl_categ); | |
1406 if (list) { | |
1407 char *prefix = g_strndup(row, ptr_inputline-row); | |
1408 // Init completion | |
1409 new_completion(prefix, list); | |
1410 g_free(prefix); | |
1411 // Now complete | |
98 | 1412 cchar = complete(); |
1413 if (cchar) | |
1414 scr_insert_text(cchar); | |
103 | 1415 completion_started = TRUE; |
98 | 1416 } |
103 | 1417 } else { // Completion already initialized |
1418 char *c; | |
1419 guint back = cancel_completion(); | |
1420 // Remove $back chars | |
1421 ptr_inputline -= back; | |
1422 c = ptr_inputline; | |
1423 for ( ; *c ; c++) | |
1424 *c = *(c+back); | |
1425 // Now complete again | |
1426 cchar = complete(); | |
1427 if (cchar) | |
1428 scr_insert_text(cchar); | |
102 | 1429 } |
98 | 1430 } |
1431 | |
1432 void scr_cancel_current_completion(void) | |
1433 { | |
1434 char *c; | |
1435 guint back = cancel_completion(); | |
1436 // Remove $back chars | |
1437 ptr_inputline -= back; | |
1438 c = ptr_inputline; | |
1439 for ( ; *c ; c++) | |
1440 *c = *(c+back); | |
1441 } | |
1442 | |
1443 void scr_end_current_completion(void) | |
1444 { | |
1445 done_completion(); | |
1446 completion_started = FALSE; | |
1447 } | |
1448 | |
24 | 1449 // check_offset(int direction) |
1450 // Check inputline_offset value, and make sure the cursor is inside the | |
1451 // screen. | |
1452 inline void check_offset(int direction) | |
1453 { | |
1454 // Left side | |
1455 if (inputline_offset && direction <= 0) { | |
1456 while (ptr_inputline <= (char*)&inputLine + inputline_offset) { | |
1457 if (inputline_offset) { | |
1458 inputline_offset -= 5; | |
1459 if (inputline_offset < 0) | |
1460 inputline_offset = 0; | |
1461 } | |
1462 } | |
1463 } | |
1464 // Right side | |
1465 if (direction >= 0) { | |
1466 while (ptr_inputline >= inputline_offset + (char*)&inputLine + maxX) | |
1467 inputline_offset += 5; | |
1468 } | |
1469 } | |
1470 | |
312
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1471 inline void refresh_inputline(void) |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1472 { |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1473 mvwprintw(inputWnd, 0,0, "%s", inputLine + inputline_offset); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1474 wclrtoeol(inputWnd); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1475 if (*ptr_inputline) |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1476 wmove(inputWnd, 0, ptr_inputline - (char*)&inputLine - inputline_offset); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1477 } |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1478 |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1479 void scr_handle_sigint(void) |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1480 { |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1481 scr_LogPrint("In screen. completion_started=%d", completion_started); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1482 // Same as Ctrl-g, now |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1483 scr_cancel_current_completion(); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1484 scr_end_current_completion(); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1485 check_offset(-1); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1486 refresh_inputline(); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1487 } |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1488 |
44 | 1489 // process_key(key) |
1490 // Handle the pressed key, in the command line (bottom). | |
29 | 1491 int process_key(int key) |
24 | 1492 { |
1493 if (isprint(key)) { | |
1494 char tmpLine[INPUTLINE_LENGTH+1]; | |
1495 | |
1496 // Check the line isn't too long | |
1497 if (strlen(inputLine) >= INPUTLINE_LENGTH) | |
1498 return 0; | |
1499 | |
1500 // Insert char | |
1501 strcpy(tmpLine, ptr_inputline); | |
1502 *ptr_inputline++ = key; | |
1503 strcpy(ptr_inputline, tmpLine); | |
1504 check_offset(1); | |
1505 } else { | |
1506 switch(key) { | |
232 | 1507 case 8: // Ctrl-h |
1508 case 127: // Backspace too | |
24 | 1509 case KEY_BACKSPACE: |
1510 if (ptr_inputline != (char*)&inputLine) { | |
42 | 1511 char *c = --ptr_inputline; |
1512 for ( ; *c ; c++) | |
1513 *c = *(c+1); | |
24 | 1514 check_offset(-1); |
1515 } | |
1516 break; | |
238 | 1517 case KEY_DC:// Del |
24 | 1518 if (*ptr_inputline) |
1519 strcpy(ptr_inputline, ptr_inputline+1); | |
1520 break; | |
1521 case KEY_LEFT: | |
1522 if (ptr_inputline != (char*)&inputLine) { | |
1523 ptr_inputline--; | |
1524 check_offset(-1); | |
1525 } | |
1526 break; | |
1527 case KEY_RIGHT: | |
1528 if (*ptr_inputline) | |
1529 ptr_inputline++; | |
1530 check_offset(1); | |
1531 break; | |
98 | 1532 case 7: // Ctrl-g |
1533 scr_cancel_current_completion(); | |
1534 scr_end_current_completion(); | |
1535 check_offset(-1); | |
1536 break; | |
24 | 1537 case 9: // Tab |
98 | 1538 scr_handle_tab(); |
1539 check_offset(0); | |
24 | 1540 break; |
1541 case '\n': // Enter | |
263 | 1542 case 15: // Ctrl-o ("accept-line-and-down-history") |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1543 scr_CheckAutoAway(TRUE); |
29 | 1544 if (process_line(inputLine)) |
24 | 1545 return 255; |
173 | 1546 // Add line to history |
1547 scr_cmdhisto_addline(inputLine); | |
1548 // Reset the line | |
24 | 1549 ptr_inputline = inputLine; |
1550 *ptr_inputline = 0; | |
1551 inputline_offset = 0; | |
263 | 1552 |
1553 if (key == '\n') // Enter | |
1554 { | |
1555 // Reset history line pointer | |
1556 cmdhisto_cur = NULL; | |
1557 } else { // down-history | |
1558 // Use next history line instead of a blank line | |
1559 const char *l = scr_cmdhisto_next("", 0); | |
1560 if (l) | |
1561 strcpy(inputLine, l); | |
1562 // Reset backup history line | |
1563 cmdhisto_backup[0] = 0; | |
1564 } | |
24 | 1565 break; |
1566 case KEY_UP: | |
175 | 1567 { |
1568 const char *l = scr_cmdhisto_prev(inputLine, | |
1569 ptr_inputline-inputLine); | |
1570 if (l) { | |
1571 strcpy(inputLine, l); | |
1572 } | |
1573 } | |
24 | 1574 break; |
1575 case KEY_DOWN: | |
175 | 1576 { |
1577 const char *l = scr_cmdhisto_next(inputLine, | |
1578 ptr_inputline-inputLine); | |
1579 if (l) { | |
1580 strcpy(inputLine, l); | |
1581 } | |
1582 } | |
24 | 1583 break; |
1584 case KEY_PPAGE: | |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1585 scr_CheckAutoAway(TRUE); |
175 | 1586 scr_RosterUp(); |
24 | 1587 break; |
1588 case KEY_NPAGE: | |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1589 scr_CheckAutoAway(TRUE); |
175 | 1590 scr_RosterDown(); |
24 | 1591 break; |
1592 case KEY_HOME: | |
1593 case 1: | |
1594 ptr_inputline = inputLine; | |
1595 inputline_offset = 0; | |
1596 break; | |
1597 case KEY_END: | |
1598 case 5: | |
1599 for (; *ptr_inputline; ptr_inputline++) ; | |
1600 check_offset(1); | |
1601 break; | |
1602 case 21: // Ctrl-u | |
1603 strcpy(inputLine, ptr_inputline); | |
1604 ptr_inputline = inputLine; | |
1605 inputline_offset = 0; | |
1606 break; | |
1607 case KEY_EOL: | |
1608 case 11: // Ctrl-k | |
1609 *ptr_inputline = 0; | |
1610 break; | |
1611 case 16: // Ctrl-p | |
175 | 1612 scr_ScrollUp(); |
24 | 1613 break; |
1614 case 14: // Ctrl-n | |
175 | 1615 scr_ScrollDown(); |
24 | 1616 break; |
196 | 1617 case 17: // Ctrl-q |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1618 scr_CheckAutoAway(TRUE); |
236 | 1619 scr_RosterUnreadMessage(1); // next unread message |
196 | 1620 break; |
195 | 1621 case 20: // Ctrl-t |
1622 readline_transpose_chars(); | |
1623 break; | |
194 | 1624 case 23: // Ctrl-w |
195 | 1625 readline_backward_kill_word(); |
194 | 1626 break; |
24 | 1627 case 27: // ESC |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1628 scr_CheckAutoAway(TRUE); |
24 | 1629 currentWindow = NULL; |
1630 chatmode = FALSE; | |
119 | 1631 if (current_buddy) |
1632 buddy_setflags(BUDDATA(current_buddy), ROSTER_FLAG_LOCK, FALSE); | |
24 | 1633 top_panel(chatPanel); |
1634 top_panel(inputPanel); | |
157 | 1635 update_panels(); |
24 | 1636 break; |
151 | 1637 case 12: // Ctrl-l |
1638 case KEY_RESIZE: | |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1639 scr_CheckAutoAway(TRUE); |
151 | 1640 scr_Resize(); |
1641 break; | |
24 | 1642 default: |
288 | 1643 { |
1644 const gchar *boundcmd = isbound(key); | |
1645 if (boundcmd) { | |
1646 gchar *cmd = g_strdup_printf("/%s", boundcmd); | |
322
da138cdebf04
Implement auto-away mode
Mikael Berthe <mikael@lilotux.net>
parents:
314
diff
changeset
|
1647 scr_CheckAutoAway(TRUE); |
288 | 1648 if (process_command(cmd)) |
1649 return 255; | |
1650 g_free(cmd); | |
1651 } else { | |
1652 scr_LogPrint("Unknown key=%d", key); | |
1653 if (utf8_mode) | |
1654 scr_LogPrint("WARNING: UTF-8 not yet supported!"); | |
1655 } | |
1656 } | |
24 | 1657 } |
1658 } | |
157 | 1659 if (completion_started && key != 9 && key != KEY_RESIZE) |
98 | 1660 scr_end_current_completion(); |
312
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1661 refresh_inputline(); |
f0b7ff2df7e8
Ctrl-C does not terminate mcabber
Mikael Berthe <mikael@lilotux.net>
parents:
307
diff
changeset
|
1662 if (!update_roster) |
157 | 1663 doupdate(); |
24 | 1664 return 0; |
1665 } |