| 436 |
436 |
| 437 aol_icon(invite->window); |
437 aol_icon(invite->window); |
| 438 |
438 |
| 439 } |
439 } |
| 440 gtk_widget_show(invite); |
440 gtk_widget_show(invite); |
| |
441 } |
| |
442 |
| |
443 void tab_complete(struct conversation *c) |
| |
444 { |
| |
445 int pos = GTK_EDITABLE(c->entry)->current_pos; |
| |
446 int start = pos; |
| |
447 int most_matched = -1; |
| |
448 char *entered, *partial = NULL; |
| |
449 char *text; |
| |
450 GList *matches = NULL; |
| |
451 GList *nicks = c->in_room; |
| |
452 |
| |
453 /* if there's nothing there just return */ |
| |
454 if (!start) |
| |
455 return; |
| |
456 |
| |
457 text = gtk_editable_get_chars(GTK_EDITABLE(c->entry), 0, pos); |
| |
458 |
| |
459 /* if we're at the end of ": " we need to move back 2 spaces */ |
| |
460 if (start >= 2 && text[start - 1] == ' ' && text[start - 2] == ':') |
| |
461 start -= 2; |
| |
462 |
| |
463 /* find the start of the word that we're tabbing */ |
| |
464 while (start > 0 && text[start - 1] != ' ') |
| |
465 start--; |
| |
466 |
| |
467 entered = text + start; |
| |
468 if (chat_options & OPT_CHAT_OLD_STYLE_TAB) { |
| |
469 if (strlen(entered) >= 2 && !strncmp(": ", entered + strlen(entered) - 2, 2)) |
| |
470 entered[strlen(entered) - 2] = 0; |
| |
471 } |
| |
472 |
| |
473 if (!strlen(entered)) { |
| |
474 g_free(text); |
| |
475 return; |
| |
476 } |
| |
477 |
| |
478 debug_printf("checking tab-completion for %s\n", entered); |
| |
479 |
| |
480 while (nicks) { |
| |
481 char *nick = nicks->data; |
| |
482 /* this checks to see if the current nick could be a completion */ |
| |
483 if (g_strncasecmp(nick, entered, strlen(entered))) { |
| |
484 if (nick[0] != '+' && nick[0] != '@') { |
| |
485 nicks = nicks->next; |
| |
486 continue; |
| |
487 } |
| |
488 if (g_strncasecmp(nick + 1, entered, strlen(entered))) { |
| |
489 if (nick[0] != '@' && nick[1] != '+') { |
| |
490 nicks = nicks->next; |
| |
491 continue; |
| |
492 } |
| |
493 if (g_strncasecmp(nick + 2, entered, strlen(entered))) { |
| |
494 nicks = nicks->next; |
| |
495 continue; |
| |
496 } |
| |
497 else |
| |
498 nick += 2; |
| |
499 } else |
| |
500 nick++; |
| |
501 } |
| |
502 /* if we're here, it's a possible completion */ |
| |
503 debug_printf("possible completion: %s\n", nick); |
| |
504 |
| |
505 /* if we're doing old-style, just fill in the completion */ |
| |
506 if (chat_options & OPT_CHAT_OLD_STYLE_TAB) { |
| |
507 gtk_editable_delete_text(GTK_EDITABLE(c->entry), start, pos); |
| |
508 if (strlen(nick) == strlen(entered)) { |
| |
509 nicks = nicks->next ? nicks->next : c->in_room; |
| |
510 nick = nicks->data; |
| |
511 if (*nick == '@') |
| |
512 nick++; |
| |
513 if (*nick == '+') |
| |
514 nick++; |
| |
515 } |
| |
516 |
| |
517 if (start == 0) { |
| |
518 char *tmp = g_strdup_printf("%s: ", nick); |
| |
519 int t = start; |
| |
520 gtk_editable_insert_text(GTK_EDITABLE(c->entry), tmp, strlen(tmp), &start); |
| |
521 if (t == start) { |
| |
522 t = start + strlen(tmp); |
| |
523 gtk_editable_set_position(GTK_EDITABLE(c->entry), t); |
| |
524 } |
| |
525 g_free(tmp); |
| |
526 } else { |
| |
527 int t = start; |
| |
528 gtk_editable_insert_text(GTK_EDITABLE(c->entry), nick, strlen(nick), &start); |
| |
529 if (t == start) { |
| |
530 t = start + strlen(nick); |
| |
531 gtk_editable_set_position(GTK_EDITABLE(c->entry), t); |
| |
532 } |
| |
533 } |
| |
534 g_free(text); |
| |
535 return; |
| |
536 } |
| |
537 |
| |
538 /* we're only here if we're doing new style */ |
| |
539 if (most_matched == -1) { |
| |
540 /* this will only get called once, since from now on most_matched is >= 0 */ |
| |
541 most_matched = strlen(nick); |
| |
542 partial = g_strdup(nick); |
| |
543 } else if (most_matched) { |
| |
544 while (g_strncasecmp(nick, partial, most_matched)) |
| |
545 most_matched--; |
| |
546 partial[most_matched] = 0; |
| |
547 } |
| |
548 matches = g_list_append(matches, nick); |
| |
549 |
| |
550 nicks = nicks->next; |
| |
551 } |
| |
552 /* we're only here if we're doing new style */ |
| |
553 |
| |
554 /* if there weren't any matches, return */ |
| |
555 if (!matches) { |
| |
556 /* if matches isn't set partials won't be either */ |
| |
557 g_free(text); |
| |
558 return; |
| |
559 } |
| |
560 |
| |
561 gtk_editable_delete_text(GTK_EDITABLE(c->entry), start, pos); |
| |
562 if (!matches->next) { |
| |
563 /* there was only one match. fill it in. */ |
| |
564 if (start == 0) { |
| |
565 char *tmp = g_strdup_printf("%s: ", (char *)matches->data); |
| |
566 int t = start; |
| |
567 gtk_editable_insert_text(GTK_EDITABLE(c->entry), tmp, strlen(tmp), &start); |
| |
568 if (t == start) { |
| |
569 t = start + strlen(tmp); |
| |
570 gtk_editable_set_position(GTK_EDITABLE(c->entry), t); |
| |
571 } |
| |
572 g_free(tmp); |
| |
573 } else { |
| |
574 gtk_editable_insert_text(GTK_EDITABLE(c->entry), matches->data, strlen(matches->data), &start); |
| |
575 } |
| |
576 matches = g_list_remove(matches, matches->data); |
| |
577 } else { |
| |
578 /* there were lots of matches, fill in as much as possible and display all of them */ |
| |
579 char *addthis = g_malloc0(1); |
| |
580 int t = start; |
| |
581 while (matches) { |
| |
582 char *tmp = addthis; |
| |
583 addthis = g_strconcat(tmp, matches->data, " ", NULL); |
| |
584 g_free(tmp); |
| |
585 matches = g_list_remove(matches, matches->data); |
| |
586 } |
| |
587 write_to_conv(c, addthis, WFLAG_NOLOG, NULL, time(NULL)); |
| |
588 gtk_editable_insert_text(GTK_EDITABLE(c->entry), partial, strlen(partial), &start); |
| |
589 if (t == start) { |
| |
590 t = start + strlen(partial); |
| |
591 gtk_editable_set_position(GTK_EDITABLE(c->entry), t); |
| |
592 } |
| |
593 g_free(addthis); |
| |
594 } |
| |
595 |
| |
596 g_free(text); |
| |
597 g_free(partial); |
| 441 } |
598 } |
| 442 |
599 |
| 443 gboolean meify(char *message) |
600 gboolean meify(char *message) |
| 444 { |
601 { |
| 445 /* read /me-ify : if the message (post-HTML) starts with /me, remove |
602 /* read /me-ify : if the message (post-HTML) starts with /me, remove |