Added autobuild tools
This commit is contained in:
396
src/command.c
Normal file
396
src/command.c
Normal file
@@ -0,0 +1,396 @@
|
||||
/*
|
||||
* command.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "command.h"
|
||||
#include "contact_list.h"
|
||||
#include "history.h"
|
||||
#include "jabber.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "preferences.h"
|
||||
#include "prof_autocomplete.h"
|
||||
|
||||
static gboolean _handle_command(const char * const command,
|
||||
const char * const inp);
|
||||
static gboolean _cmd_quit(const char * const inp);
|
||||
static gboolean _cmd_help(const char * const inp);
|
||||
static gboolean _cmd_who(const char * const inp);
|
||||
static gboolean _cmd_ros(const char * const inp);
|
||||
static gboolean _cmd_connect(const char * const inp);
|
||||
static gboolean _cmd_msg(const char * const inp);
|
||||
static gboolean _cmd_close(const char * const inp);
|
||||
static gboolean _cmd_set_beep(const char * const inp);
|
||||
static gboolean _cmd_set_notify(const char * const inp);
|
||||
static gboolean _cmd_set_flash(const char * const inp);
|
||||
static gboolean _cmd_set_showsplash(const char * const inp);
|
||||
static gboolean _cmd_away(const char * const inp);
|
||||
static gboolean _cmd_online(const char * const inp);
|
||||
static gboolean _cmd_dnd(const char * const inp);
|
||||
static gboolean _cmd_chat(const char * const inp);
|
||||
static gboolean _cmd_xa(const char * const inp);
|
||||
static gboolean _cmd_default(const char * const inp);
|
||||
static void _update_presence(const jabber_presence_t presence,
|
||||
const char * const show, const char * const inp);
|
||||
|
||||
struct cmd_t {
|
||||
const gchar *cmd;
|
||||
gboolean (*func)(const char * const inp);
|
||||
};
|
||||
|
||||
static PAutocomplete commands_ac;
|
||||
|
||||
static struct cmd_t commands[] = {
|
||||
{ "/away", _cmd_away },
|
||||
{ "/beep", _cmd_set_beep },
|
||||
{ "/notify", _cmd_set_notify },
|
||||
{ "/chat", _cmd_chat },
|
||||
{ "/close", _cmd_close },
|
||||
{ "/connect", _cmd_connect },
|
||||
{ "/dnd", _cmd_dnd },
|
||||
{ "/flash", _cmd_set_flash },
|
||||
{ "/help", _cmd_help },
|
||||
{ "/msg", _cmd_msg },
|
||||
{ "/online", _cmd_online },
|
||||
{ "/quit", _cmd_quit },
|
||||
{ "/ros", _cmd_ros },
|
||||
{ "/showsplash", _cmd_set_showsplash },
|
||||
{ "/who", _cmd_who },
|
||||
{ "/xa", _cmd_xa },
|
||||
};
|
||||
|
||||
static const int num_cmds = 15;
|
||||
|
||||
gboolean process_input(char *inp)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
|
||||
g_strstrip(inp);
|
||||
|
||||
if (strlen(inp) > 0)
|
||||
history_append(inp);
|
||||
|
||||
if (strlen(inp) == 0) {
|
||||
result = TRUE;
|
||||
} else if (inp[0] == '/') {
|
||||
char inp_cpy[strlen(inp) + 1];
|
||||
strcpy(inp_cpy, inp);
|
||||
char *command = strtok(inp_cpy, " ");
|
||||
result = _handle_command(command, inp);
|
||||
} else {
|
||||
result = _cmd_default(inp);
|
||||
}
|
||||
|
||||
inp_clear();
|
||||
reset_search_attempts();
|
||||
win_page_off();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
void command_init(void)
|
||||
{
|
||||
commands_ac = p_autocomplete_new();
|
||||
|
||||
int i;
|
||||
for (i = 0; i < num_cmds; i++) {
|
||||
struct cmd_t *pcmd = commands+i;
|
||||
p_autocomplete_add(commands_ac, (gchar *)pcmd->cmd);
|
||||
}
|
||||
|
||||
history_init();
|
||||
}
|
||||
|
||||
char * cmd_complete(char *inp)
|
||||
{
|
||||
return p_autocomplete_complete(commands_ac, inp);
|
||||
}
|
||||
|
||||
void reset_command_completer(void)
|
||||
{
|
||||
p_autocomplete_reset(commands_ac);
|
||||
}
|
||||
|
||||
static gboolean _handle_command(const char * const command, const char * const inp)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_cmds; i++) {
|
||||
struct cmd_t *pcmd = commands+i;
|
||||
if (strcmp(pcmd->cmd, command) == 0) {
|
||||
return (pcmd->func(inp));
|
||||
}
|
||||
}
|
||||
|
||||
return _cmd_default(inp);
|
||||
}
|
||||
|
||||
static gboolean _cmd_connect(const char * const inp)
|
||||
{
|
||||
gboolean result = FALSE;
|
||||
jabber_conn_status_t conn_status = jabber_connection_status();
|
||||
|
||||
if ((conn_status != JABBER_DISCONNECTED) && (conn_status != JABBER_STARTED)) {
|
||||
cons_show("You are either connected already, or a login is in process.");
|
||||
result = TRUE;
|
||||
} else if (strlen(inp) < 10) {
|
||||
cons_show("Usage: /connect user@host");
|
||||
result = TRUE;
|
||||
} else {
|
||||
char *user;
|
||||
user = strndup(inp+9, strlen(inp)-9);
|
||||
status_bar_get_password();
|
||||
status_bar_refresh();
|
||||
char passwd[21];
|
||||
inp_block();
|
||||
inp_get_password(passwd);
|
||||
inp_non_block();
|
||||
|
||||
conn_status = jabber_connect(user, passwd);
|
||||
if (conn_status == JABBER_CONNECTING)
|
||||
cons_show("Connecting...");
|
||||
if (conn_status == JABBER_DISCONNECTED)
|
||||
cons_bad_show("Connection to server failed.");
|
||||
|
||||
result = TRUE;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static gboolean _cmd_quit(const char * const inp)
|
||||
{
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_help(const char * const inp)
|
||||
{
|
||||
cons_help();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_ros(const char * const inp)
|
||||
{
|
||||
jabber_conn_status_t conn_status = jabber_connection_status();
|
||||
|
||||
if (conn_status != JABBER_CONNECTED)
|
||||
cons_show("You are not currently connected.");
|
||||
else
|
||||
jabber_roster_request();
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_who(const char * const inp)
|
||||
{
|
||||
jabber_conn_status_t conn_status = jabber_connection_status();
|
||||
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show("You are not currently connected.");
|
||||
} else {
|
||||
GSList *list = get_contact_list();
|
||||
cons_show_online_contacts(list);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_msg(const char * const inp)
|
||||
{
|
||||
char *usr = NULL;
|
||||
char *msg = NULL;
|
||||
|
||||
jabber_conn_status_t conn_status = jabber_connection_status();
|
||||
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show("You are not currently connected.");
|
||||
} else {
|
||||
// copy input
|
||||
char inp_cpy[strlen(inp) + 1];
|
||||
strcpy(inp_cpy, inp);
|
||||
|
||||
// get user
|
||||
strtok(inp_cpy, " ");
|
||||
usr = strtok(NULL, " ");
|
||||
if ((usr != NULL) && (strlen(inp) > (5 + strlen(usr) + 1))) {
|
||||
// get message
|
||||
msg = strndup(inp+5+strlen(usr)+1, strlen(inp)-(5+strlen(usr)+1));
|
||||
if (msg != NULL) {
|
||||
jabber_send(msg, usr);
|
||||
win_show_outgoing_msg("me", usr, msg);
|
||||
} else {
|
||||
cons_show("Usage: /msg user@host message");
|
||||
}
|
||||
} else {
|
||||
cons_show("Usage: /msg user@host message");
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_close(const char * const inp)
|
||||
{
|
||||
if (!win_close_win())
|
||||
cons_bad_command(inp);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_set_beep(const char * const inp)
|
||||
{
|
||||
if (strcmp(inp, "/beep on") == 0) {
|
||||
cons_show("Sound enabled.");
|
||||
prefs_set_beep(TRUE);
|
||||
} else if (strcmp(inp, "/beep off") == 0) {
|
||||
cons_show("Sound disabled.");
|
||||
prefs_set_beep(FALSE);
|
||||
} else {
|
||||
cons_show("Usage: /beep <on/off>");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_set_notify(const char * const inp)
|
||||
{
|
||||
if (strcmp(inp, "/notify on") == 0) {
|
||||
cons_show("Desktop notifications enabled.");
|
||||
prefs_set_notify(TRUE);
|
||||
} else if (strcmp(inp, "/notify off") == 0) {
|
||||
cons_show("Desktop notifications disabled.");
|
||||
prefs_set_notify(FALSE);
|
||||
} else {
|
||||
cons_show("Usage: /notify <on/off>");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_set_flash(const char * const inp)
|
||||
{
|
||||
if (strcmp(inp, "/flash on") == 0) {
|
||||
cons_show("Screen flash enabled.");
|
||||
prefs_set_flash(TRUE);
|
||||
} else if (strcmp(inp, "/flash off") == 0) {
|
||||
cons_show("Screen flash disabled.");
|
||||
prefs_set_flash(FALSE);
|
||||
} else {
|
||||
cons_show("Usage: /flash <on/off>");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_set_showsplash(const char * const inp)
|
||||
{
|
||||
if (strcmp(inp, "/showsplash on") == 0) {
|
||||
cons_show("Splash screen enabled.");
|
||||
prefs_set_showsplash(TRUE);
|
||||
} else if (strcmp(inp, "/showsplash off") == 0) {
|
||||
cons_show("Splash screen disabled.");
|
||||
prefs_set_showsplash(FALSE);
|
||||
} else {
|
||||
cons_show("Usage: /showsplash <on/off>");
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_away(const char * const inp)
|
||||
{
|
||||
_update_presence(PRESENCE_AWAY, "away", inp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_online(const char * const inp)
|
||||
{
|
||||
_update_presence(PRESENCE_ONLINE, "online", inp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_dnd(const char * const inp)
|
||||
{
|
||||
_update_presence(PRESENCE_DND, "dnd", inp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_chat(const char * const inp)
|
||||
{
|
||||
_update_presence(PRESENCE_CHAT, "chat", inp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_xa(const char * const inp)
|
||||
{
|
||||
_update_presence(PRESENCE_XA, "xa", inp);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean _cmd_default(const char * const inp)
|
||||
{
|
||||
if (win_in_chat()) {
|
||||
char *recipient = win_get_recipient();
|
||||
jabber_send(inp, recipient);
|
||||
win_show_outgoing_msg("me", recipient, inp);
|
||||
free(recipient);
|
||||
} else {
|
||||
cons_bad_command(inp);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void _update_presence(const jabber_presence_t presence,
|
||||
const char * const show, const char * const inp)
|
||||
{
|
||||
char *msg;
|
||||
if (strlen(inp) > strlen(show) + 2) {
|
||||
msg = strndup(inp+(strlen(show) + 2), strlen(inp)-(strlen(show) + 2));
|
||||
} else {
|
||||
msg = NULL;
|
||||
}
|
||||
|
||||
jabber_conn_status_t conn_status = jabber_connection_status();
|
||||
|
||||
if (conn_status != JABBER_CONNECTED) {
|
||||
cons_show("You are not currently connected.");
|
||||
} else {
|
||||
jabber_update_presence(presence, msg);
|
||||
title_bar_set_status(presence);
|
||||
if (msg != NULL) {
|
||||
char str[14 + strlen(show) + 3 + strlen(msg) + 2];
|
||||
sprintf(str, "Status set to %s, \"%s\"", show, msg);
|
||||
cons_show(str);
|
||||
free(msg);
|
||||
} else {
|
||||
char str[14 + strlen(show) + 1];
|
||||
sprintf(str, "Status set to %s", show);
|
||||
cons_show(str);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
31
src/command.h
Normal file
31
src/command.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* command.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMMAND_H
|
||||
#define COMMAND_H
|
||||
|
||||
void command_init(void);
|
||||
gboolean process_input(char *inp);
|
||||
char * cmd_complete(char *inp);
|
||||
void reset_command_completer(void);
|
||||
|
||||
#endif
|
||||
29
src/common.c
Normal file
29
src/common.c
Normal file
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* common.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void p_slist_free_full(GSList *items, GDestroyNotify free_func)
|
||||
{
|
||||
g_slist_foreach (items, (GFunc) free_func, NULL);
|
||||
g_slist_free (items);
|
||||
}
|
||||
54
src/common.h
Normal file
54
src/common.h
Normal file
@@ -0,0 +1,54 @@
|
||||
/*
|
||||
* common.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef COMMON_H
|
||||
#define COMMON_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef enum {
|
||||
JABBER_STARTED,
|
||||
JABBER_CONNECTING,
|
||||
JABBER_CONNECTED,
|
||||
JABBER_DISCONNECTED
|
||||
} jabber_conn_status_t;
|
||||
|
||||
typedef enum {
|
||||
PRESENCE_OFFLINE,
|
||||
PRESENCE_ONLINE,
|
||||
PRESENCE_AWAY,
|
||||
PRESENCE_DND,
|
||||
PRESENCE_CHAT,
|
||||
PRESENCE_XA
|
||||
} jabber_presence_t;
|
||||
|
||||
#if !GLIB_CHECK_VERSION(2,28,0)
|
||||
#define g_slist_free_full(items, free_func) p_slist_free_full(items, free_func)
|
||||
#endif
|
||||
|
||||
#ifndef NOTIFY_CHECK_VERSION
|
||||
#define notify_notification_new(summary, body, icon) notify_notification_new(summary, body, icon, NULL)
|
||||
#endif
|
||||
|
||||
void p_slist_free_full(GSList *items, GDestroyNotify free_func);
|
||||
|
||||
#endif
|
||||
108
src/contact.c
Normal file
108
src/contact.c
Normal file
@@ -0,0 +1,108 @@
|
||||
/*
|
||||
* contact.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "contact.h"
|
||||
|
||||
struct p_contact_t {
|
||||
char *name;
|
||||
char *show;
|
||||
char *status;
|
||||
};
|
||||
|
||||
PContact p_contact_new(const char * const name, const char * const show,
|
||||
const char * const status)
|
||||
{
|
||||
PContact contact = malloc(sizeof(struct p_contact_t));
|
||||
contact->name = strdup(name);
|
||||
|
||||
if (show == NULL || (strcmp(show, "") == 0))
|
||||
contact->show = strdup("online");
|
||||
else
|
||||
contact->show = strdup(show);
|
||||
|
||||
if (status != NULL)
|
||||
contact->status = strdup(status);
|
||||
else
|
||||
contact->status = NULL;
|
||||
|
||||
return contact;
|
||||
}
|
||||
|
||||
PContact p_contact_copy(PContact contact)
|
||||
{
|
||||
PContact copy = malloc(sizeof(struct p_contact_t));
|
||||
copy->name = strdup(contact->name);
|
||||
copy->show = strdup(contact->show);
|
||||
|
||||
if (contact->status != NULL)
|
||||
copy->status = strdup(contact->status);
|
||||
else
|
||||
copy->status = NULL;
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
void p_contact_free(PContact contact)
|
||||
{
|
||||
free(contact->name);
|
||||
|
||||
if (contact->show != NULL) {
|
||||
free(contact->show);
|
||||
contact->show = NULL;
|
||||
}
|
||||
if (contact->status != NULL) {
|
||||
free(contact->status);
|
||||
contact->status = NULL;
|
||||
}
|
||||
|
||||
free(contact);
|
||||
contact = NULL;
|
||||
}
|
||||
|
||||
const char * p_contact_name(const PContact contact)
|
||||
{
|
||||
return contact->name;
|
||||
}
|
||||
|
||||
const char * p_contact_show(const PContact contact)
|
||||
{
|
||||
return contact->show;
|
||||
}
|
||||
|
||||
const char * p_contact_status(const PContact contact)
|
||||
{
|
||||
return contact->status;
|
||||
}
|
||||
|
||||
int p_contacts_equal_deep(const PContact c1, const PContact c2)
|
||||
{
|
||||
int name_eq = (g_strcmp0(c1->name, c2->name) == 0);
|
||||
int show_eq = (g_strcmp0(c1->show, c2->show) == 0);
|
||||
int status_eq = (g_strcmp0(c1->status, c2->status) == 0);
|
||||
|
||||
return (name_eq && show_eq && status_eq);
|
||||
}
|
||||
37
src/contact.h
Normal file
37
src/contact.h
Normal file
@@ -0,0 +1,37 @@
|
||||
/*
|
||||
* contact.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTACT_H
|
||||
#define CONTACT_H
|
||||
|
||||
typedef struct p_contact_t *PContact;
|
||||
|
||||
PContact p_contact_new(const char * const name, const char * const show,
|
||||
const char * const status);
|
||||
PContact p_contact_copy(PContact contact);
|
||||
void p_contact_free(PContact contact);
|
||||
const char * p_contact_name(PContact contact);
|
||||
const char * p_contact_show(PContact contact);
|
||||
const char * p_contact_status(PContact contact);
|
||||
int p_contacts_equal_deep(const PContact c1, const PContact c2);
|
||||
|
||||
#endif
|
||||
72
src/contact_list.c
Normal file
72
src/contact_list.c
Normal file
@@ -0,0 +1,72 @@
|
||||
/*
|
||||
* contact_list.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "contact.h"
|
||||
#include "contact_list.h"
|
||||
#include "prof_autocomplete.h"
|
||||
|
||||
static PAutocomplete ac;
|
||||
|
||||
void contact_list_init(void)
|
||||
{
|
||||
ac = p_obj_autocomplete_new((PStrFunc)p_contact_name,
|
||||
(PCopyFunc)p_contact_copy,
|
||||
(PEqualDeepFunc)p_contacts_equal_deep,
|
||||
(GDestroyNotify)p_contact_free);
|
||||
}
|
||||
|
||||
void contact_list_clear(void)
|
||||
{
|
||||
p_autocomplete_clear(ac);
|
||||
}
|
||||
|
||||
void reset_search_attempts(void)
|
||||
{
|
||||
p_autocomplete_reset(ac);
|
||||
}
|
||||
|
||||
gboolean contact_list_remove(const char * const name)
|
||||
{
|
||||
return p_autocomplete_remove(ac, name);
|
||||
}
|
||||
|
||||
gboolean contact_list_add(const char * const name, const char * const show,
|
||||
const char * const status)
|
||||
{
|
||||
return p_autocomplete_add(ac, p_contact_new(name, show, status));
|
||||
}
|
||||
|
||||
GSList * get_contact_list(void)
|
||||
{
|
||||
return p_autocomplete_get_list(ac);
|
||||
}
|
||||
|
||||
char * find_contact(char *search_str)
|
||||
{
|
||||
return p_autocomplete_complete(ac, search_str);
|
||||
}
|
||||
39
src/contact_list.h
Normal file
39
src/contact_list.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* contact_list.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef CONTACT_LIST_H
|
||||
#define CONTACT_LIST_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "contact.h"
|
||||
|
||||
void contact_list_init(void);
|
||||
void contact_list_clear(void);
|
||||
void reset_search_attempts(void);
|
||||
gboolean contact_list_add(const char * const name, const char * const show,
|
||||
const char * const status);
|
||||
gboolean contact_list_remove(const char * const name);
|
||||
GSList * get_contact_list(void);
|
||||
char * find_contact(char *search_str);
|
||||
|
||||
#endif
|
||||
69
src/history.c
Normal file
69
src/history.c
Normal file
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* history.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "prof_history.h"
|
||||
|
||||
#define MAX_HISTORY 100
|
||||
|
||||
static PHistory history;
|
||||
|
||||
void _stringify_input(char *inp, int size, char *string);
|
||||
|
||||
void history_init(void)
|
||||
{
|
||||
history = p_history_new(MAX_HISTORY);
|
||||
}
|
||||
|
||||
void history_append(char *inp)
|
||||
{
|
||||
p_history_append(history, inp);
|
||||
}
|
||||
|
||||
char * history_previous(char *inp, int *size)
|
||||
{
|
||||
char inp_str[*size + 1];
|
||||
_stringify_input(inp, *size, inp_str);
|
||||
|
||||
return p_history_previous(history, inp_str);
|
||||
}
|
||||
|
||||
char *history_next(char *inp, int *size)
|
||||
{
|
||||
char inp_str[*size + 1];
|
||||
_stringify_input(inp, *size, inp_str);
|
||||
|
||||
return p_history_next(history, inp_str);
|
||||
}
|
||||
|
||||
void _stringify_input(char *inp, int size, char *string)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
string[i] = inp[i];
|
||||
}
|
||||
string[size] = '\0';
|
||||
}
|
||||
|
||||
|
||||
32
src/history.h
Normal file
32
src/history.h
Normal file
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* history.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#ifndef HISTORY_H
|
||||
#define HISTORY_H
|
||||
|
||||
void history_init(void);
|
||||
void history_append(char *inp);
|
||||
char *history_previous(char *inp, int *size);
|
||||
char *history_next(char *inp, int *size);
|
||||
|
||||
#endif
|
||||
316
src/input_win.c
Normal file
316
src/input_win.c
Normal file
@@ -0,0 +1,316 @@
|
||||
/*
|
||||
* input_win.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
* Non blocking input char handling
|
||||
*
|
||||
* *size - holds the current size of input
|
||||
* *input - holds the current input string, NOT null terminated at this point
|
||||
* *ch - getch will put a charater here if there was any input
|
||||
*
|
||||
* The example below shows the values of size, input, a call to wgetyx to
|
||||
* find the current cursor location, and the index of the input string.
|
||||
*
|
||||
* size : " 7 "
|
||||
* input : " example "
|
||||
* inp_x : "012345678"
|
||||
* index : " 0123456 " (inp_x - 1)
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "history.h"
|
||||
#include "preferences.h"
|
||||
#include "util.h"
|
||||
#include "command.h"
|
||||
|
||||
static WINDOW *inp_win;
|
||||
|
||||
static int _handle_edit(const int ch, char *input, int *size);
|
||||
static int _printable(const int ch);
|
||||
static void _replace_input(char *input, const char * const new_input, int *size);
|
||||
|
||||
void create_input_window(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
inp_win = newwin(1, cols, rows-1, 0);
|
||||
wbkgd(inp_win, COLOR_PAIR(1));
|
||||
keypad(inp_win, TRUE);
|
||||
// wattrset(inp_win, A_BOLD);
|
||||
wmove(inp_win, 0, 1);
|
||||
wrefresh(inp_win);
|
||||
}
|
||||
|
||||
void inp_win_resize(const char * const input, const int size)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
mvwin(inp_win, rows-1, 0);
|
||||
wresize(inp_win, 1, cols);
|
||||
wrefresh(inp_win);
|
||||
}
|
||||
|
||||
void inp_clear(void)
|
||||
{
|
||||
wclear(inp_win);
|
||||
wmove(inp_win, 0, 1);
|
||||
wrefresh(inp_win);
|
||||
}
|
||||
|
||||
void inp_non_block(void)
|
||||
{
|
||||
wtimeout(inp_win, 500);
|
||||
}
|
||||
|
||||
void inp_block(void)
|
||||
{
|
||||
wtimeout(inp_win, -1);
|
||||
}
|
||||
|
||||
void inp_get_char(int *ch, char *input, int *size)
|
||||
{
|
||||
int inp_y = 0;
|
||||
int inp_x = 0;
|
||||
int i;
|
||||
|
||||
|
||||
// echo off, and get some more input
|
||||
noecho();
|
||||
*ch = wgetch(inp_win);
|
||||
|
||||
// if it wasn't an arrow key etc
|
||||
if (!_handle_edit(*ch, input, size)) {
|
||||
if (_printable(*ch)) {
|
||||
getyx(inp_win, inp_y, inp_x);
|
||||
|
||||
// handle insert if not at end of input
|
||||
if (inp_x <= *size) {
|
||||
winsch(inp_win, *ch);
|
||||
wmove(inp_win, inp_y, inp_x+1);
|
||||
|
||||
for (i = *size; i > inp_x -1; i--)
|
||||
input[i] = input[i-1];
|
||||
input[inp_x -1] = *ch;
|
||||
|
||||
(*size)++;
|
||||
|
||||
// otherwise just append
|
||||
} else {
|
||||
waddch(inp_win, *ch);
|
||||
input[(*size)++] = *ch;
|
||||
}
|
||||
|
||||
reset_search_attempts();
|
||||
reset_login_search();
|
||||
reset_command_completer();
|
||||
}
|
||||
}
|
||||
|
||||
echo();
|
||||
}
|
||||
|
||||
void inp_get_password(char *passwd)
|
||||
{
|
||||
wclear(inp_win);
|
||||
noecho();
|
||||
mvwgetnstr(inp_win, 0, 1, passwd, 20);
|
||||
wmove(inp_win, 0, 1);
|
||||
echo();
|
||||
status_bar_clear();
|
||||
}
|
||||
|
||||
void inp_put_back(void)
|
||||
{
|
||||
wrefresh(inp_win);
|
||||
}
|
||||
|
||||
/*
|
||||
* Deal with command editing, return 1 if ch was an edit
|
||||
* key press: up, down, left, right or backspace
|
||||
* return 0 if it wasnt
|
||||
*/
|
||||
static int _handle_edit(const int ch, char *input, int *size)
|
||||
{
|
||||
int i;
|
||||
char *prev = NULL;
|
||||
char *next = NULL;
|
||||
char *found = NULL;
|
||||
char *auto_msg = NULL;
|
||||
int inp_y = 0;
|
||||
int inp_x = 0;
|
||||
char inp_cpy[*size];
|
||||
|
||||
getyx(inp_win, inp_y, inp_x);
|
||||
|
||||
switch(ch) {
|
||||
|
||||
case 127:
|
||||
case KEY_BACKSPACE:
|
||||
reset_search_attempts();
|
||||
if (*size > 0) {
|
||||
|
||||
// if at end, delete last char
|
||||
if (inp_x > *size) {
|
||||
wmove(inp_win, inp_y, inp_x-1);
|
||||
wdelch(inp_win);
|
||||
(*size)--;
|
||||
|
||||
// if in middle, delete and shift chars left
|
||||
} else if (inp_x > 1 && inp_x <= *size) {
|
||||
for (i = inp_x-1; i < *size; i++)
|
||||
input[i-1] = input[i];
|
||||
(*size)--;
|
||||
|
||||
inp_clear();
|
||||
for (i = 0; i < *size; i++)
|
||||
waddch(inp_win, input[i]);
|
||||
wmove(inp_win, 0, inp_x -1);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
case KEY_DC: // DEL
|
||||
if (inp_x <= *size) {
|
||||
wdelch(inp_win);
|
||||
|
||||
// if not last char, shift chars left
|
||||
if (inp_x < *size)
|
||||
for (i = inp_x-1; i < *size; i++)
|
||||
input[i] = input[i+1];
|
||||
|
||||
(*size)--;
|
||||
}
|
||||
return 1;
|
||||
|
||||
case KEY_LEFT:
|
||||
if (inp_x > 1)
|
||||
wmove(inp_win, inp_y, inp_x-1);
|
||||
return 1;
|
||||
|
||||
case KEY_RIGHT:
|
||||
if (inp_x <= *size )
|
||||
wmove(inp_win, inp_y, inp_x+1);
|
||||
return 1;
|
||||
|
||||
case KEY_UP:
|
||||
prev = history_previous(input, size);
|
||||
if (prev)
|
||||
_replace_input(input, prev, size);
|
||||
return 1;
|
||||
|
||||
case KEY_DOWN:
|
||||
next = history_next(input, size);
|
||||
if (next)
|
||||
_replace_input(input, next, size);
|
||||
return 1;
|
||||
|
||||
case KEY_HOME:
|
||||
wmove(inp_win, inp_y, 1);
|
||||
return 1;
|
||||
|
||||
case KEY_END:
|
||||
wmove(inp_win, inp_y, (*size) + 1);
|
||||
return 1;
|
||||
|
||||
case 9: // tab
|
||||
|
||||
// autocomplete commands
|
||||
if ((strncmp(input, "/", 1) == 0) && (!str_contains(input, *size, ' '))) {
|
||||
for(i = 0; i < *size; i++) {
|
||||
inp_cpy[i] = input[i];
|
||||
}
|
||||
inp_cpy[i] = '\0';
|
||||
found = cmd_complete(inp_cpy);
|
||||
if (found != NULL) {
|
||||
auto_msg = (char *) malloc((strlen(found) + 1) * sizeof(char));
|
||||
strcpy(auto_msg, found);
|
||||
_replace_input(input, auto_msg, size);
|
||||
free(auto_msg);
|
||||
free(found);
|
||||
}
|
||||
|
||||
// autcomplete /msg recipient
|
||||
} else if ((strncmp(input, "/msg ", 5) == 0) && (*size > 5)) {
|
||||
for(i = 5; i < *size; i++) {
|
||||
inp_cpy[i-5] = input[i];
|
||||
}
|
||||
inp_cpy[(*size) - 5] = '\0';
|
||||
found = find_contact(inp_cpy);
|
||||
if (found != NULL) {
|
||||
auto_msg = (char *) malloc((5 + (strlen(found) + 1)) * sizeof(char));
|
||||
strcpy(auto_msg, "/msg ");
|
||||
strcat(auto_msg, found);
|
||||
_replace_input(input, auto_msg, size);
|
||||
free(auto_msg);
|
||||
free(found);
|
||||
}
|
||||
|
||||
// autocomplete /connect username
|
||||
} else if ((strncmp(input, "/connect ", 9) == 0) && (*size > 9)) {
|
||||
for(i = 9; i < *size; i++) {
|
||||
inp_cpy[i-9] = input[i];
|
||||
}
|
||||
inp_cpy[(*size) - 9] = '\0';
|
||||
found = find_login(inp_cpy);
|
||||
if (found != NULL) {
|
||||
auto_msg = (char *) malloc((9 + (strlen(found) + 1)) * sizeof(char));
|
||||
strcpy(auto_msg, "/connect ");
|
||||
strcat(auto_msg, found);
|
||||
_replace_input(input, auto_msg, size);
|
||||
free(auto_msg);
|
||||
free(found);
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
|
||||
default:
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static int _printable(const int ch)
|
||||
{
|
||||
return (ch != ERR && ch != '\n' &&
|
||||
ch != KEY_PPAGE && ch != KEY_NPAGE &&
|
||||
ch != KEY_F(1) && ch != KEY_F(2) && ch != KEY_F(3) &&
|
||||
ch != KEY_F(4) && ch != KEY_F(5) && ch != KEY_F(6) &&
|
||||
ch != KEY_F(7) && ch != KEY_F(8) && ch != KEY_F(9) &&
|
||||
ch != KEY_F(10) && ch!= KEY_F(11) && ch != KEY_F(12) &&
|
||||
ch != KEY_IC && ch != KEY_EIC && ch != KEY_RESIZE);
|
||||
}
|
||||
|
||||
static void _replace_input(char *input, const char * const new_input, int *size)
|
||||
{
|
||||
int i;
|
||||
|
||||
strcpy(input, new_input);
|
||||
*size = strlen(input);
|
||||
inp_clear();
|
||||
for (i = 0; i < *size; i++)
|
||||
waddch(inp_win, input[i]);
|
||||
}
|
||||
410
src/jabber.c
Normal file
410
src/jabber.c
Normal file
@@ -0,0 +1,410 @@
|
||||
/*
|
||||
* jabber.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <strophe.h>
|
||||
|
||||
#include "jabber.h"
|
||||
#include "common.h"
|
||||
#include "log.h"
|
||||
#include "contact_list.h"
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "preferences.h"
|
||||
|
||||
#define PING_INTERVAL 120000 // 2 minutes
|
||||
|
||||
// log reference
|
||||
extern FILE *logp;
|
||||
|
||||
static struct _jabber_conn_t {
|
||||
xmpp_log_t *log;
|
||||
xmpp_ctx_t *ctx;
|
||||
xmpp_conn_t *conn;
|
||||
jabber_conn_status_t conn_status;
|
||||
jabber_presence_t presence;
|
||||
int tls_disabled;
|
||||
} jabber_conn;
|
||||
|
||||
void xmpp_file_logger(void * const userdata, const xmpp_log_level_t level,
|
||||
const char * const area, const char * const msg);
|
||||
|
||||
static const xmpp_log_t file_log = { &xmpp_file_logger, XMPP_LEVEL_DEBUG };
|
||||
|
||||
xmpp_log_t *xmpp_get_file_logger()
|
||||
{
|
||||
return (xmpp_log_t*) &file_log;
|
||||
}
|
||||
|
||||
void xmpp_file_logger(void * const userdata, const xmpp_log_level_t level,
|
||||
const char * const area, const char * const msg)
|
||||
{
|
||||
log_msg(area, msg);
|
||||
}
|
||||
|
||||
// private XMPP handlers
|
||||
static void _jabber_conn_handler(xmpp_conn_t * const conn,
|
||||
const xmpp_conn_event_t status, const int error,
|
||||
xmpp_stream_error_t * const stream_error, void * const userdata);
|
||||
|
||||
static int _jabber_message_handler(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza, void * const userdata);
|
||||
|
||||
static int _roster_handler(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza, void * const userdata);
|
||||
|
||||
static int _jabber_presence_handler(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza, void * const userdata);
|
||||
|
||||
static int _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata);
|
||||
|
||||
void jabber_init(const int disable_tls)
|
||||
{
|
||||
jabber_conn.conn_status = JABBER_STARTED;
|
||||
jabber_conn.presence = PRESENCE_OFFLINE;
|
||||
jabber_conn.tls_disabled = disable_tls;
|
||||
}
|
||||
|
||||
jabber_conn_status_t jabber_connection_status(void)
|
||||
{
|
||||
return (jabber_conn.conn_status);
|
||||
}
|
||||
|
||||
jabber_conn_status_t jabber_connect(const char * const user,
|
||||
const char * const passwd)
|
||||
{
|
||||
xmpp_initialize();
|
||||
|
||||
jabber_conn.log = xmpp_get_file_logger();
|
||||
jabber_conn.ctx = xmpp_ctx_new(NULL, jabber_conn.log);
|
||||
jabber_conn.conn = xmpp_conn_new(jabber_conn.ctx);
|
||||
|
||||
xmpp_conn_set_jid(jabber_conn.conn, user);
|
||||
xmpp_conn_set_pass(jabber_conn.conn, passwd);
|
||||
|
||||
if (jabber_conn.tls_disabled)
|
||||
xmpp_conn_disable_tls(jabber_conn.conn);
|
||||
|
||||
int connect_status = xmpp_connect_client(jabber_conn.conn, NULL, 0,
|
||||
_jabber_conn_handler, jabber_conn.ctx);
|
||||
|
||||
if (connect_status == 0)
|
||||
jabber_conn.conn_status = JABBER_CONNECTING;
|
||||
else
|
||||
jabber_conn.conn_status = JABBER_DISCONNECTED;
|
||||
|
||||
return jabber_conn.conn_status;
|
||||
}
|
||||
|
||||
const char * jabber_get_jid(void)
|
||||
{
|
||||
return xmpp_conn_get_jid(jabber_conn.conn);
|
||||
}
|
||||
|
||||
void jabber_disconnect(void)
|
||||
{
|
||||
if (jabber_conn.conn_status == JABBER_CONNECTED) {
|
||||
xmpp_conn_release(jabber_conn.conn);
|
||||
xmpp_ctx_free(jabber_conn.ctx);
|
||||
xmpp_shutdown();
|
||||
jabber_conn.conn_status = JABBER_DISCONNECTED;
|
||||
jabber_conn.presence = PRESENCE_OFFLINE;
|
||||
}
|
||||
}
|
||||
|
||||
void jabber_process_events(void)
|
||||
{
|
||||
if (jabber_conn.conn_status == JABBER_CONNECTED
|
||||
|| jabber_conn.conn_status == JABBER_CONNECTING)
|
||||
xmpp_run_once(jabber_conn.ctx, 10);
|
||||
}
|
||||
|
||||
void jabber_send(const char * const msg, const char * const recipient)
|
||||
{
|
||||
char *coded_msg = str_replace(msg, "&", "&");
|
||||
|
||||
xmpp_stanza_t *reply, *body, *text;
|
||||
|
||||
reply = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(reply, "message");
|
||||
xmpp_stanza_set_type(reply, "chat");
|
||||
xmpp_stanza_set_attribute(reply, "to", recipient);
|
||||
|
||||
body = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(body, "body");
|
||||
|
||||
text = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_text(text, coded_msg);
|
||||
xmpp_stanza_add_child(body, text);
|
||||
xmpp_stanza_add_child(reply, body);
|
||||
|
||||
xmpp_send(jabber_conn.conn, reply);
|
||||
xmpp_stanza_release(reply);
|
||||
}
|
||||
|
||||
void jabber_roster_request(void)
|
||||
{
|
||||
xmpp_stanza_t *iq, *query;
|
||||
|
||||
iq = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(iq, "iq");
|
||||
xmpp_stanza_set_type(iq, "get");
|
||||
xmpp_stanza_set_id(iq, "roster");
|
||||
|
||||
query = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(query, "query");
|
||||
xmpp_stanza_set_ns(query, XMPP_NS_ROSTER);
|
||||
|
||||
xmpp_stanza_add_child(iq, query);
|
||||
xmpp_stanza_release(query);
|
||||
xmpp_send(jabber_conn.conn, iq);
|
||||
xmpp_stanza_release(iq);
|
||||
}
|
||||
|
||||
void jabber_update_presence(jabber_presence_t status, const char * const msg)
|
||||
{
|
||||
jabber_conn.presence = status;
|
||||
|
||||
xmpp_stanza_t *pres, *show;
|
||||
|
||||
pres = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(pres, "presence");
|
||||
|
||||
if (status != PRESENCE_ONLINE) {
|
||||
show = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(show, "show");
|
||||
xmpp_stanza_t *text = xmpp_stanza_new(jabber_conn.ctx);
|
||||
|
||||
if (status == PRESENCE_AWAY)
|
||||
xmpp_stanza_set_text(text, "away");
|
||||
else if (status == PRESENCE_DND)
|
||||
xmpp_stanza_set_text(text, "dnd");
|
||||
else if (status == PRESENCE_CHAT)
|
||||
xmpp_stanza_set_text(text, "chat");
|
||||
else if (status == PRESENCE_XA)
|
||||
xmpp_stanza_set_text(text, "xa");
|
||||
else
|
||||
xmpp_stanza_set_text(text, "online");
|
||||
|
||||
xmpp_stanza_add_child(show, text);
|
||||
xmpp_stanza_add_child(pres, show);
|
||||
xmpp_stanza_release(text);
|
||||
xmpp_stanza_release(show);
|
||||
}
|
||||
|
||||
if (msg != NULL) {
|
||||
xmpp_stanza_t *status = xmpp_stanza_new(jabber_conn.ctx);
|
||||
xmpp_stanza_set_name(status, "status");
|
||||
xmpp_stanza_t *text = xmpp_stanza_new(jabber_conn.ctx);
|
||||
|
||||
xmpp_stanza_set_text(text, msg);
|
||||
|
||||
xmpp_stanza_add_child(status, text);
|
||||
xmpp_stanza_add_child(pres, status);
|
||||
xmpp_stanza_release(text);
|
||||
xmpp_stanza_release(status);
|
||||
}
|
||||
|
||||
xmpp_send(jabber_conn.conn, pres);
|
||||
xmpp_stanza_release(pres);
|
||||
}
|
||||
|
||||
static int _jabber_message_handler(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza, void * const userdata)
|
||||
{
|
||||
xmpp_stanza_t *body = xmpp_stanza_get_child_by_name(stanza, "body");
|
||||
if(body == NULL)
|
||||
return 1;
|
||||
|
||||
char *type = xmpp_stanza_get_attribute(stanza, "type");
|
||||
if(strcmp(type, "error") == 0)
|
||||
return 1;
|
||||
|
||||
char *message = xmpp_stanza_get_text(body);
|
||||
char *from = xmpp_stanza_get_attribute(stanza, "from");
|
||||
win_show_incomming_msg(from, message);
|
||||
win_page_off();
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void _jabber_conn_handler(xmpp_conn_t * const conn,
|
||||
const xmpp_conn_event_t status, const int error,
|
||||
xmpp_stream_error_t * const stream_error, void * const userdata)
|
||||
{
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
|
||||
if (status == XMPP_CONN_CONNECT) {
|
||||
const char *jid = xmpp_conn_get_jid(conn);
|
||||
const char *msg = " logged in successfully.";
|
||||
char line[strlen(jid) + 1 + strlen(msg) + 1];
|
||||
sprintf(line, "%s %s", jid, msg);
|
||||
title_bar_set_status(PRESENCE_ONLINE);
|
||||
|
||||
cons_show(line);
|
||||
win_page_off();
|
||||
status_bar_print_message(jid);
|
||||
status_bar_refresh();
|
||||
|
||||
xmpp_stanza_t* pres;
|
||||
xmpp_handler_add(conn, _jabber_message_handler, NULL, "message", NULL, ctx);
|
||||
xmpp_handler_add(conn, _jabber_presence_handler, NULL, "presence", NULL, ctx);
|
||||
xmpp_id_handler_add(conn, _roster_handler, "roster", ctx);
|
||||
xmpp_timed_handler_add(conn, _ping_timed_handler, PING_INTERVAL, ctx);
|
||||
|
||||
pres = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_name(pres, "presence");
|
||||
xmpp_send(conn, pres);
|
||||
xmpp_stanza_release(pres);
|
||||
|
||||
prefs_add_login(jid);
|
||||
|
||||
jabber_conn.conn_status = JABBER_CONNECTED;
|
||||
jabber_conn.presence = PRESENCE_ONLINE;
|
||||
}
|
||||
else {
|
||||
if (jabber_conn.conn_status == JABBER_CONNECTED) {
|
||||
cons_bad_show("Lost connection.");
|
||||
win_disconnected();
|
||||
} else {
|
||||
cons_bad_show("Login failed.");
|
||||
}
|
||||
win_page_off();
|
||||
log_msg(CONN, "disconnected");
|
||||
xmpp_stop(ctx);
|
||||
jabber_conn.conn_status = JABBER_DISCONNECTED;
|
||||
jabber_conn.presence = PRESENCE_OFFLINE;
|
||||
}
|
||||
}
|
||||
|
||||
static int _roster_handler(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza, void * const userdata)
|
||||
{
|
||||
xmpp_stanza_t *query, *item;
|
||||
char *type, *name, *jid;
|
||||
|
||||
type = xmpp_stanza_get_type(stanza);
|
||||
|
||||
if (strcmp(type, "error") == 0)
|
||||
log_msg(CONN, "ERROR: query failed");
|
||||
else {
|
||||
query = xmpp_stanza_get_child_by_name(stanza, "query");
|
||||
cons_show("Roster:");
|
||||
|
||||
item = xmpp_stanza_get_children(query);
|
||||
while (item != NULL) {
|
||||
name = xmpp_stanza_get_attribute(item, "name");
|
||||
jid = xmpp_stanza_get_attribute(item, "jid");
|
||||
|
||||
if (name != NULL) {
|
||||
char line[strlen(name) + 2 + strlen(jid) + 1 + 1];
|
||||
sprintf(line, "%s (%s)", name, jid);
|
||||
cons_show(line);
|
||||
|
||||
} else {
|
||||
char line[strlen(jid) + 1];
|
||||
sprintf(line, "%s", jid);
|
||||
cons_show(line);
|
||||
}
|
||||
|
||||
item = xmpp_stanza_get_next(item);
|
||||
|
||||
win_page_off();
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _ping_timed_handler(xmpp_conn_t * const conn, void * const userdata)
|
||||
{
|
||||
if (jabber_conn.conn_status == JABBER_CONNECTED) {
|
||||
xmpp_ctx_t *ctx = (xmpp_ctx_t *)userdata;
|
||||
|
||||
xmpp_stanza_t *iq, *ping;
|
||||
|
||||
iq = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_name(iq, "iq");
|
||||
xmpp_stanza_set_type(iq, "get");
|
||||
xmpp_stanza_set_id(iq, "c2s1");
|
||||
|
||||
ping = xmpp_stanza_new(ctx);
|
||||
xmpp_stanza_set_name(ping, "ping");
|
||||
|
||||
// FIXME add ping namespace to libstrophe
|
||||
xmpp_stanza_set_ns(ping, "urn:xmpp:ping");
|
||||
|
||||
xmpp_stanza_add_child(iq, ping);
|
||||
xmpp_stanza_release(ping);
|
||||
xmpp_send(conn, iq);
|
||||
xmpp_stanza_release(iq);
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int _jabber_presence_handler(xmpp_conn_t * const conn,
|
||||
xmpp_stanza_t * const stanza, void * const userdata)
|
||||
{
|
||||
const char *jid = xmpp_conn_get_jid(jabber_conn.conn);
|
||||
char jid_cpy[strlen(jid) + 1];
|
||||
strcpy(jid_cpy, jid);
|
||||
char *short_jid = strtok(jid_cpy, "/");
|
||||
|
||||
char *from = xmpp_stanza_get_attribute(stanza, "from");
|
||||
char *short_from = strtok(from, "/");
|
||||
char *type = xmpp_stanza_get_attribute(stanza, "type");
|
||||
|
||||
char *show_str, *status_str;
|
||||
|
||||
xmpp_stanza_t *show = xmpp_stanza_get_child_by_name(stanza, "show");
|
||||
if (show != NULL)
|
||||
show_str = xmpp_stanza_get_text(show);
|
||||
else
|
||||
show_str = NULL;
|
||||
|
||||
xmpp_stanza_t *status = xmpp_stanza_get_child_by_name(stanza, "status");
|
||||
if (status != NULL)
|
||||
status_str = xmpp_stanza_get_text(status);
|
||||
else
|
||||
status_str = NULL;
|
||||
|
||||
if (strcmp(short_jid, short_from) !=0) {
|
||||
if (type == NULL) {// online
|
||||
gboolean result = contact_list_add(short_from, show_str, status_str);
|
||||
if (result) {
|
||||
win_contact_online(short_from, show_str, status_str);
|
||||
}
|
||||
} else {// offline
|
||||
gboolean result = contact_list_remove(short_from);
|
||||
if (result) {
|
||||
win_contact_offline(short_from, show_str, status_str);
|
||||
}
|
||||
}
|
||||
|
||||
win_page_off();
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
40
src/jabber.h
Normal file
40
src/jabber.h
Normal file
@@ -0,0 +1,40 @@
|
||||
/*
|
||||
* jabber.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef JABBER_H
|
||||
#define JABBER_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void jabber_init(const int disable_tls);
|
||||
jabber_conn_status_t jabber_connection_status(void);
|
||||
jabber_presence_t jabber_presence_status(void);
|
||||
jabber_conn_status_t jabber_connect(const char * const user,
|
||||
const char * const passwd);
|
||||
void jabber_disconnect(void);
|
||||
void jabber_roster_request(void);
|
||||
void jabber_process_events(void);
|
||||
void jabber_send(const char * const msg, const char * const recipient);
|
||||
const char * jabber_get_jid(void);
|
||||
void jabber_update_presence(jabber_presence_t status, const char * const msg);
|
||||
|
||||
#endif
|
||||
43
src/log.c
Normal file
43
src/log.c
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* log.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "log.h"
|
||||
|
||||
extern FILE *logp;
|
||||
|
||||
void log_msg(const char * const area, const char * const msg)
|
||||
{
|
||||
fprintf(logp, "%s DEBUG: %s\n", area, msg);
|
||||
}
|
||||
|
||||
void log_init(void)
|
||||
{
|
||||
logp = fopen("profanity.log", "a");
|
||||
log_msg(PROF, "Starting Profanity...");
|
||||
}
|
||||
|
||||
void log_close(void)
|
||||
{
|
||||
fclose(logp);
|
||||
}
|
||||
39
src/log.h
Normal file
39
src/log.h
Normal file
@@ -0,0 +1,39 @@
|
||||
/*
|
||||
* log.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef LOG_H
|
||||
#define LOG_H
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
// log areas
|
||||
#define PROF "prof"
|
||||
#define CONN "conn"
|
||||
|
||||
// file log
|
||||
FILE *logp;
|
||||
|
||||
void log_init(void);
|
||||
void log_msg(const char * const area, const char * const msg);
|
||||
void log_close(void);
|
||||
|
||||
#endif
|
||||
52
src/main.c
Normal file
52
src/main.c
Normal file
@@ -0,0 +1,52 @@
|
||||
/*
|
||||
* main.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "profanity.h"
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
int disable_tls = 0;
|
||||
|
||||
// more than one argument
|
||||
if (argc > 2) {
|
||||
printf("Usage: profanity [-notls]\n");
|
||||
return 1;
|
||||
|
||||
// argument is not -notls
|
||||
} else if (argc == 2) {
|
||||
char *arg1 = argv[1];
|
||||
if (strcmp(arg1, "-notls") != 0) {
|
||||
printf("Usage: profanity [-notls]\n");
|
||||
return 1;
|
||||
} else {
|
||||
disable_tls = 1;
|
||||
}
|
||||
}
|
||||
|
||||
profanity_init(disable_tls);
|
||||
profanity_run();
|
||||
|
||||
return 0;
|
||||
}
|
||||
300
src/preferences.c
Normal file
300
src/preferences.c
Normal file
@@ -0,0 +1,300 @@
|
||||
/*
|
||||
* preferences.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "log.h"
|
||||
#include "preferences.h"
|
||||
#include "prof_autocomplete.h"
|
||||
|
||||
static GString *prefs_loc;
|
||||
static GKeyFile *prefs;
|
||||
|
||||
// search logins list
|
||||
static PAutocomplete ac;
|
||||
|
||||
struct colour_string_t {
|
||||
char *str;
|
||||
NCURSES_COLOR_T colour;
|
||||
};
|
||||
|
||||
static int num_colours = 9;
|
||||
static struct colour_string_t colours[] = {
|
||||
{ "default", -1 },
|
||||
{ "white", COLOR_WHITE },
|
||||
{ "green", COLOR_GREEN },
|
||||
{ "red", COLOR_RED },
|
||||
{ "yellow", COLOR_YELLOW },
|
||||
{ "blue", COLOR_BLUE },
|
||||
{ "cyan", COLOR_CYAN },
|
||||
{ "black", COLOR_BLACK },
|
||||
{ "magenta", COLOR_MAGENTA },
|
||||
};
|
||||
|
||||
// colour preferences
|
||||
static struct colours_t {
|
||||
NCURSES_COLOR_T bkgnd;
|
||||
NCURSES_COLOR_T text;
|
||||
NCURSES_COLOR_T online;
|
||||
NCURSES_COLOR_T offline;
|
||||
NCURSES_COLOR_T err;
|
||||
NCURSES_COLOR_T inc;
|
||||
NCURSES_COLOR_T bar;
|
||||
NCURSES_COLOR_T bar_draw;
|
||||
NCURSES_COLOR_T bar_text;
|
||||
} colour_prefs;
|
||||
|
||||
static NCURSES_COLOR_T _lookup_colour(const char * const colour);
|
||||
static void _set_colour(gchar *val, NCURSES_COLOR_T *pref,
|
||||
NCURSES_COLOR_T def);
|
||||
static void _load_colours(void);
|
||||
static void _save_prefs(void);
|
||||
|
||||
void prefs_load(void)
|
||||
{
|
||||
ac = p_autocomplete_new();
|
||||
prefs_loc = g_string_new(getenv("HOME"));
|
||||
g_string_append(prefs_loc, "/.profanity");
|
||||
|
||||
prefs = g_key_file_new();
|
||||
g_key_file_load_from_file(prefs, prefs_loc->str, G_KEY_FILE_NONE, NULL);
|
||||
|
||||
// create the logins searchable list for autocompletion
|
||||
gsize njids;
|
||||
gchar **jids =
|
||||
g_key_file_get_string_list(prefs, "connections", "logins", &njids, NULL);
|
||||
|
||||
gsize i;
|
||||
for (i = 0; i < njids; i++) {
|
||||
p_autocomplete_add(ac, jids[i]);
|
||||
}
|
||||
|
||||
_load_colours();
|
||||
}
|
||||
|
||||
static NCURSES_COLOR_T _lookup_colour(const char * const colour)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < num_colours; i++) {
|
||||
if (strcmp(colours[i].str, colour) == 0) {
|
||||
return colours[i].colour;
|
||||
}
|
||||
}
|
||||
|
||||
return -99;
|
||||
}
|
||||
|
||||
static void _set_colour(gchar *val, NCURSES_COLOR_T *pref,
|
||||
NCURSES_COLOR_T def)
|
||||
{
|
||||
if(!val) {
|
||||
*pref = def;
|
||||
} else {
|
||||
NCURSES_COLOR_T col = _lookup_colour(val);
|
||||
if (col == -99) {
|
||||
*pref = def;
|
||||
} else {
|
||||
*pref = col;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void _load_colours(void)
|
||||
{
|
||||
gchar *bkgnd_val = g_key_file_get_string(prefs, "colours", "bkgnd", NULL);
|
||||
_set_colour(bkgnd_val, &colour_prefs.bkgnd, -1);
|
||||
|
||||
gchar *text_val = g_key_file_get_string(prefs, "colours", "text", NULL);
|
||||
_set_colour(text_val, &colour_prefs.text, COLOR_WHITE);
|
||||
|
||||
gchar *online_val = g_key_file_get_string(prefs, "colours", "online", NULL);
|
||||
_set_colour(online_val, &colour_prefs.online, COLOR_GREEN);
|
||||
|
||||
gchar *offline_val = g_key_file_get_string(prefs, "colours", "offline", NULL);
|
||||
_set_colour(offline_val, &colour_prefs.offline, COLOR_CYAN);
|
||||
|
||||
gchar *err_val = g_key_file_get_string(prefs, "colours", "err", NULL);
|
||||
_set_colour(err_val, &colour_prefs.err, COLOR_RED);
|
||||
|
||||
gchar *inc_val = g_key_file_get_string(prefs, "colours", "inc", NULL);
|
||||
_set_colour(inc_val, &colour_prefs.inc, COLOR_YELLOW);
|
||||
|
||||
gchar *bar_val = g_key_file_get_string(prefs, "colours", "bar", NULL);
|
||||
_set_colour(bar_val, &colour_prefs.bar, COLOR_BLUE);
|
||||
|
||||
gchar *bar_draw_val = g_key_file_get_string(prefs, "colours", "bar_draw", NULL);
|
||||
_set_colour(bar_draw_val, &colour_prefs.bar_draw, COLOR_CYAN);
|
||||
|
||||
gchar *bar_text_val = g_key_file_get_string(prefs, "colours", "bar_text", NULL);
|
||||
_set_colour(bar_text_val, &colour_prefs.bar_text, COLOR_WHITE);
|
||||
}
|
||||
|
||||
char * find_login(char *prefix)
|
||||
{
|
||||
return p_autocomplete_complete(ac, prefix);
|
||||
}
|
||||
|
||||
void reset_login_search(void)
|
||||
{
|
||||
p_autocomplete_reset(ac);
|
||||
}
|
||||
|
||||
gboolean prefs_get_beep(void)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, "ui", "beep", NULL);
|
||||
}
|
||||
|
||||
void prefs_set_beep(gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, "ui", "beep", value);
|
||||
_save_prefs();
|
||||
}
|
||||
|
||||
gboolean prefs_get_notify(void)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, "ui", "notify", NULL);
|
||||
}
|
||||
|
||||
void prefs_set_notify(gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, "ui", "notify", value);
|
||||
_save_prefs();
|
||||
}
|
||||
|
||||
gboolean prefs_get_flash(void)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, "ui", "flash", NULL);
|
||||
}
|
||||
|
||||
void prefs_set_flash(gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, "ui", "flash", value);
|
||||
_save_prefs();
|
||||
}
|
||||
|
||||
void prefs_add_login(const char *jid)
|
||||
{
|
||||
gsize njids;
|
||||
gchar **jids =
|
||||
g_key_file_get_string_list(prefs, "connections", "logins", &njids, NULL);
|
||||
|
||||
// no logins remembered yet
|
||||
if (jids == NULL) {
|
||||
njids = 1;
|
||||
jids = (gchar**) g_malloc(sizeof(gchar *) * 2);
|
||||
jids[0] = g_strdup(jid);
|
||||
jids[1] = NULL;
|
||||
g_key_file_set_string_list(prefs, "connections", "logins",
|
||||
(const gchar * const *)jids, njids);
|
||||
_save_prefs();
|
||||
g_strfreev(jids);
|
||||
|
||||
return;
|
||||
} else {
|
||||
gsize i;
|
||||
for (i = 0; i < njids; i++) {
|
||||
if (strcmp(jid, jids[i]) == 0) {
|
||||
g_strfreev(jids);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// jid not found, add to the list
|
||||
jids = (gchar **) g_realloc(jids, (sizeof(gchar *) * (njids+2)));
|
||||
jids[njids] = g_strdup(jid);
|
||||
njids++;
|
||||
jids[njids] = NULL;
|
||||
g_key_file_set_string_list(prefs, "connections", "logins",
|
||||
(const gchar * const *)jids, njids);
|
||||
_save_prefs();
|
||||
g_strfreev(jids);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean prefs_get_showsplash(void)
|
||||
{
|
||||
return g_key_file_get_boolean(prefs, "ui", "showsplash", NULL);
|
||||
}
|
||||
|
||||
void prefs_set_showsplash(gboolean value)
|
||||
{
|
||||
g_key_file_set_boolean(prefs, "ui", "showsplash", value);
|
||||
_save_prefs();
|
||||
}
|
||||
|
||||
static void _save_prefs(void)
|
||||
{
|
||||
gsize g_data_size;
|
||||
char *g_prefs_data = g_key_file_to_data(prefs, &g_data_size, NULL);
|
||||
g_file_set_contents(prefs_loc->str, g_prefs_data, g_data_size, NULL);
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_bkgnd()
|
||||
{
|
||||
return colour_prefs.bkgnd;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_text()
|
||||
{
|
||||
return colour_prefs.text;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_online()
|
||||
{
|
||||
return colour_prefs.online;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_offline()
|
||||
{
|
||||
return colour_prefs.offline;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_err()
|
||||
{
|
||||
return colour_prefs.err;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_inc()
|
||||
{
|
||||
return colour_prefs.inc;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_bar()
|
||||
{
|
||||
return colour_prefs.bar;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_bar_draw()
|
||||
{
|
||||
return colour_prefs.bar_draw;
|
||||
}
|
||||
|
||||
NCURSES_COLOR_T prefs_get_bar_text()
|
||||
{
|
||||
return colour_prefs.bar_text;
|
||||
}
|
||||
53
src/preferences.h
Normal file
53
src/preferences.h
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* preferences.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PREFERENCES_H
|
||||
#define PREFERENCES_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
void prefs_load(void);
|
||||
|
||||
char * find_login(char *prefix);
|
||||
void reset_login_search(void);
|
||||
|
||||
gboolean prefs_get_beep(void);
|
||||
void prefs_set_beep(gboolean value);
|
||||
gboolean prefs_get_notify(void);
|
||||
void prefs_set_notify(gboolean value);
|
||||
gboolean prefs_get_flash(void);
|
||||
void prefs_set_flash(gboolean value);
|
||||
void prefs_add_login(const char *jid);
|
||||
gboolean prefs_get_showsplash(void);
|
||||
void prefs_set_showsplash(gboolean value);
|
||||
|
||||
NCURSES_COLOR_T prefs_get_bkgnd();
|
||||
NCURSES_COLOR_T prefs_get_text();
|
||||
NCURSES_COLOR_T prefs_get_online();
|
||||
NCURSES_COLOR_T prefs_get_offline();
|
||||
NCURSES_COLOR_T prefs_get_err();
|
||||
NCURSES_COLOR_T prefs_get_inc();
|
||||
NCURSES_COLOR_T prefs_get_bar();
|
||||
NCURSES_COLOR_T prefs_get_bar_draw();
|
||||
NCURSES_COLOR_T prefs_get_bar_text();
|
||||
|
||||
#endif
|
||||
251
src/prof_autocomplete.c
Normal file
251
src/prof_autocomplete.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* prof_autocomplete.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "prof_autocomplete.h"
|
||||
|
||||
struct p_autocomplete_t {
|
||||
GSList *items;
|
||||
GSList *last_found;
|
||||
gchar *search_str;
|
||||
PStrFunc str_func;
|
||||
PCopyFunc copy_func;
|
||||
PEqualDeepFunc equal_deep_func;
|
||||
GDestroyNotify free_func;
|
||||
};
|
||||
|
||||
static gchar * _search_from(PAutocomplete ac, GSList *curr);
|
||||
static const char *_str_func_default(const char *orig);
|
||||
static const char *_copy_func_default(const char *orig);
|
||||
static int _deep_equals_func_default(const char *o1, const char *o2);
|
||||
|
||||
PAutocomplete p_autocomplete_new(void)
|
||||
{
|
||||
return p_obj_autocomplete_new(NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
PAutocomplete p_obj_autocomplete_new(PStrFunc str_func, PCopyFunc copy_func,
|
||||
PEqualDeepFunc equal_deep_func, GDestroyNotify free_func)
|
||||
{
|
||||
PAutocomplete new = malloc(sizeof(struct p_autocomplete_t));
|
||||
new->items = NULL;
|
||||
new->last_found = NULL;
|
||||
new->search_str = NULL;
|
||||
|
||||
if (str_func)
|
||||
new->str_func = str_func;
|
||||
else
|
||||
new->str_func = (PStrFunc)_str_func_default;
|
||||
|
||||
if (copy_func)
|
||||
new->copy_func = copy_func;
|
||||
else
|
||||
new->copy_func = (PCopyFunc)_copy_func_default;
|
||||
|
||||
if (free_func)
|
||||
new->free_func = free_func;
|
||||
else
|
||||
new->free_func = (GDestroyNotify)free;
|
||||
|
||||
if (equal_deep_func)
|
||||
new->equal_deep_func = equal_deep_func;
|
||||
else
|
||||
new->equal_deep_func = (PEqualDeepFunc)_deep_equals_func_default;
|
||||
|
||||
return new;
|
||||
}
|
||||
|
||||
void p_autocomplete_clear(PAutocomplete ac)
|
||||
{
|
||||
g_slist_free_full(ac->items, ac->free_func);
|
||||
ac->items = NULL;
|
||||
|
||||
p_autocomplete_reset(ac);
|
||||
}
|
||||
|
||||
void p_autocomplete_reset(PAutocomplete ac)
|
||||
{
|
||||
ac->last_found = NULL;
|
||||
if (ac->search_str != NULL) {
|
||||
free(ac->search_str);
|
||||
ac->search_str = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean p_autocomplete_add(PAutocomplete ac, void *item)
|
||||
{
|
||||
if (ac->items == NULL) {
|
||||
ac->items = g_slist_append(ac->items, item);
|
||||
return TRUE;
|
||||
} else {
|
||||
GSList *curr = ac->items;
|
||||
|
||||
while(curr) {
|
||||
|
||||
// insert
|
||||
if (g_strcmp0(ac->str_func(curr->data), ac->str_func(item)) > 0) {
|
||||
ac->items = g_slist_insert_before(ac->items,
|
||||
curr, item);
|
||||
return TRUE;
|
||||
|
||||
// update
|
||||
} else if (g_strcmp0(ac->str_func(curr->data), ac->str_func(item)) == 0) {
|
||||
// only update if data different
|
||||
if (!ac->equal_deep_func(curr->data, item)) {
|
||||
ac->free_func(curr->data);
|
||||
curr->data = item;
|
||||
return TRUE;
|
||||
} else {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
|
||||
// hit end, append
|
||||
ac->items = g_slist_append(ac->items, item);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
gboolean p_autocomplete_remove(PAutocomplete ac, const char * const item)
|
||||
{
|
||||
// reset last found if it points to the item to be removed
|
||||
if (ac->last_found != NULL)
|
||||
if (g_strcmp0(ac->str_func(ac->last_found->data), item) == 0)
|
||||
ac->last_found = NULL;
|
||||
|
||||
if (!ac->items) {
|
||||
return FALSE;
|
||||
} else {
|
||||
GSList *curr = ac->items;
|
||||
|
||||
while(curr) {
|
||||
if (g_strcmp0(ac->str_func(curr->data), item) == 0) {
|
||||
void *current_item = curr->data;
|
||||
ac->items = g_slist_remove(ac->items, curr->data);
|
||||
ac->free_func(current_item);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
GSList * p_autocomplete_get_list(PAutocomplete ac)
|
||||
{
|
||||
GSList *copy = NULL;
|
||||
GSList *curr = ac->items;
|
||||
|
||||
while(curr) {
|
||||
copy = g_slist_append(copy, ac->copy_func(curr->data));
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
|
||||
return copy;
|
||||
}
|
||||
|
||||
gchar * p_autocomplete_complete(PAutocomplete ac, gchar *search_str)
|
||||
{
|
||||
gchar *found = NULL;
|
||||
|
||||
// no items to search
|
||||
if (!ac->items)
|
||||
return NULL;
|
||||
|
||||
// first search attempt
|
||||
if (ac->last_found == NULL) {
|
||||
ac->search_str =
|
||||
(gchar *) malloc((strlen(search_str) + 1) * sizeof(gchar));
|
||||
strcpy(ac->search_str, search_str);
|
||||
|
||||
found = _search_from(ac, ac->items);
|
||||
return found;
|
||||
|
||||
// subsequent search attempt
|
||||
} else {
|
||||
// search from here+1 tp end
|
||||
found = _search_from(ac, g_slist_next(ac->last_found));
|
||||
if (found != NULL)
|
||||
return found;
|
||||
|
||||
// search from beginning
|
||||
found = _search_from(ac, ac->items);
|
||||
if (found != NULL)
|
||||
return found;
|
||||
|
||||
// we found nothing, reset search
|
||||
p_autocomplete_reset(ac);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
|
||||
static gchar * _search_from(PAutocomplete ac, GSList *curr)
|
||||
{
|
||||
while(curr) {
|
||||
|
||||
// match found
|
||||
if (strncmp(ac->str_func(curr->data),
|
||||
ac->search_str,
|
||||
strlen(ac->search_str)) == 0) {
|
||||
gchar *result =
|
||||
(gchar *) malloc((strlen(ac->str_func(curr->data)) + 1) * sizeof(gchar));
|
||||
|
||||
// set pointer to last found
|
||||
ac->last_found = curr;
|
||||
|
||||
// return the string, must be free'd by caller
|
||||
strcpy(result, ac->str_func(curr->data));
|
||||
return result;
|
||||
}
|
||||
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static const char *_str_func_default(const char *orig)
|
||||
{
|
||||
return orig;
|
||||
}
|
||||
|
||||
static const char *_copy_func_default(const char *orig)
|
||||
{
|
||||
return strdup(orig);
|
||||
}
|
||||
|
||||
static int _deep_equals_func_default(const char *o1, const char *o2)
|
||||
{
|
||||
return (strcmp(o1, o2) == 0);
|
||||
}
|
||||
44
src/prof_autocomplete.h
Normal file
44
src/prof_autocomplete.h
Normal file
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* prof_autocomplete.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROF_AUTOCOMPLETE_H
|
||||
#define PROF_AUTOCOMPLETE_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
typedef struct p_autocomplete_t *PAutocomplete;
|
||||
typedef const char * (*PStrFunc)(const void *obj);
|
||||
typedef void * (*PCopyFunc)(const void *obj);
|
||||
typedef int (*PEqualFunc)(const void *o1, const void *o2);
|
||||
typedef int (*PEqualDeepFunc)(const void *o1, const void *o2);
|
||||
|
||||
PAutocomplete p_autocomplete_new(void);
|
||||
PAutocomplete p_obj_autocomplete_new(PStrFunc str_func, PCopyFunc copy_func,
|
||||
PEqualDeepFunc equal_deep_func, GDestroyNotify free_func);
|
||||
void p_autocomplete_clear(PAutocomplete ac);
|
||||
void p_autocomplete_reset(PAutocomplete ac);
|
||||
gboolean p_autocomplete_add(PAutocomplete ac, void *item);
|
||||
gboolean p_autocomplete_remove(PAutocomplete ac, const char * const item);
|
||||
GSList * p_autocomplete_get_list(PAutocomplete ac);
|
||||
gchar * p_autocomplete_complete(PAutocomplete ac, gchar *search_str);
|
||||
|
||||
#endif
|
||||
251
src/prof_history.c
Normal file
251
src/prof_history.c
Normal file
@@ -0,0 +1,251 @@
|
||||
/*
|
||||
* prof_history.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
#include "prof_history.h"
|
||||
|
||||
struct p_history_session_t {
|
||||
GList *items;
|
||||
GList *sess_curr;
|
||||
GList *sess_new;
|
||||
GList *orig_curr;
|
||||
};
|
||||
|
||||
struct p_history_t {
|
||||
GList *items;
|
||||
guint max_size;
|
||||
struct p_history_session_t session;
|
||||
};
|
||||
|
||||
static void _replace_history_with_session(PHistory history);
|
||||
static gboolean _adding_new(PHistory history);
|
||||
static void _reset_session(PHistory history);
|
||||
static gboolean _has_session(PHistory history);
|
||||
static void _remove_first(PHistory history);
|
||||
static void _update_current_session_item(PHistory history, char *item);
|
||||
static void _add_to_history(PHistory history, char *item);
|
||||
static void _remove_last_session_item(PHistory history);
|
||||
static void _replace_current_with_original(PHistory history);
|
||||
static void _create_session(PHistory history);
|
||||
static void _session_previous(PHistory history);
|
||||
static void _session_next(PHistory history);
|
||||
|
||||
PHistory p_history_new(unsigned int size)
|
||||
{
|
||||
PHistory new_history = malloc(sizeof(struct p_history_t));
|
||||
new_history->items = NULL;
|
||||
new_history->max_size = size;
|
||||
|
||||
_reset_session(new_history);
|
||||
|
||||
return new_history;
|
||||
}
|
||||
|
||||
void p_history_append(PHistory history, char *item)
|
||||
{
|
||||
char *copied = "";
|
||||
if (item != NULL) {
|
||||
copied = strdup(item);
|
||||
}
|
||||
|
||||
if (history->items == NULL) {
|
||||
_add_to_history(history, copied);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_has_session(history)) {
|
||||
if (g_list_length(history->items) == history->max_size) {
|
||||
_remove_first(history);
|
||||
}
|
||||
|
||||
_add_to_history(history, copied);
|
||||
|
||||
} else {
|
||||
_update_current_session_item(history, copied);
|
||||
|
||||
if (_adding_new(history)) {
|
||||
if (strcmp(history->session.sess_curr->data, "") == 0) {
|
||||
_remove_last_session_item(history);
|
||||
}
|
||||
|
||||
_replace_history_with_session(history);
|
||||
|
||||
} else {
|
||||
_remove_last_session_item(history);
|
||||
|
||||
char *new = strdup(history->session.sess_curr->data);
|
||||
history->session.items = g_list_append(history->session.items, new);
|
||||
|
||||
_replace_current_with_original(history);
|
||||
_replace_history_with_session(history);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char * p_history_previous(PHistory history, char *item)
|
||||
{
|
||||
// no history
|
||||
if (history->items == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *copied = "";
|
||||
if (item != NULL) {
|
||||
copied = strdup(item);
|
||||
}
|
||||
|
||||
if (!_has_session(history)) {
|
||||
_create_session(history);
|
||||
|
||||
// add the new item
|
||||
g_list_append(history->session.items, copied);
|
||||
history->session.sess_new = g_list_last(history->session.items);
|
||||
|
||||
char *result = strdup(history->session.sess_curr->data);
|
||||
return result;
|
||||
} else {
|
||||
_update_current_session_item(history, copied);
|
||||
_session_previous(history);
|
||||
}
|
||||
|
||||
char *result = strdup(history->session.sess_curr->data);
|
||||
return result;
|
||||
}
|
||||
|
||||
char * p_history_next(PHistory history, char *item)
|
||||
{
|
||||
// no history, or no session, return NULL
|
||||
if ((history->items == NULL) || (history->session.items == NULL)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
char *copied = "";
|
||||
if (item != NULL) {
|
||||
copied = strdup(item);
|
||||
}
|
||||
|
||||
_update_current_session_item(history, copied);
|
||||
_session_next(history);
|
||||
|
||||
char *result = strdup(history->session.sess_curr->data);
|
||||
return result;
|
||||
}
|
||||
|
||||
static void _replace_history_with_session(PHistory history)
|
||||
{
|
||||
g_list_free(history->items);
|
||||
history->items = g_list_copy(history->session.items);
|
||||
|
||||
if (g_list_length(history->items) > history->max_size) {
|
||||
_remove_first(history);
|
||||
}
|
||||
|
||||
_reset_session(history);
|
||||
}
|
||||
|
||||
static gboolean _adding_new(PHistory history)
|
||||
{
|
||||
return (history->session.sess_curr ==
|
||||
g_list_last(history->session.items));
|
||||
}
|
||||
|
||||
static void _reset_session(PHistory history)
|
||||
{
|
||||
history->session.items = NULL;
|
||||
history->session.sess_curr = NULL;
|
||||
history->session.sess_new = NULL;
|
||||
history->session.orig_curr = NULL;
|
||||
}
|
||||
|
||||
static gboolean _has_session(PHistory history)
|
||||
{
|
||||
return (history->session.items != NULL);
|
||||
}
|
||||
|
||||
static void _remove_first(PHistory history)
|
||||
{
|
||||
GList *first = g_list_first(history->items);
|
||||
char *first_item = first->data;
|
||||
history->items = g_list_remove(history->items, first_item);
|
||||
}
|
||||
|
||||
static void _update_current_session_item(PHistory history, char *item)
|
||||
{
|
||||
history->session.sess_curr->data = item;
|
||||
}
|
||||
|
||||
static void _add_to_history(PHistory history, char *item)
|
||||
{
|
||||
history->items = g_list_append(history->items, item);
|
||||
}
|
||||
|
||||
static void _remove_last_session_item(PHistory history)
|
||||
{
|
||||
history->session.items = g_list_reverse(history->session.items);
|
||||
GList *first = g_list_first(history->session.items);
|
||||
history->session.items =
|
||||
g_list_remove(history->session.items, first->data);
|
||||
history->session.items = g_list_reverse(history->session.items);
|
||||
}
|
||||
|
||||
static void _replace_current_with_original(PHistory history)
|
||||
{
|
||||
history->session.sess_curr->data = strdup(history->session.orig_curr->data);
|
||||
}
|
||||
|
||||
static void _create_session(PHistory history)
|
||||
{
|
||||
history->session.items = g_list_copy(history->items);
|
||||
history->session.sess_curr = g_list_last(history->session.items);
|
||||
history->session.orig_curr = g_list_last(history->items);
|
||||
}
|
||||
|
||||
static void _session_previous(PHistory history)
|
||||
{
|
||||
history->session.sess_curr =
|
||||
g_list_previous(history->session.sess_curr);
|
||||
if (history->session.orig_curr == NULL)
|
||||
history->session.orig_curr = g_list_last(history->items);
|
||||
else
|
||||
history->session.orig_curr =
|
||||
g_list_previous(history->session.orig_curr);
|
||||
|
||||
if (history->session.sess_curr == NULL) {
|
||||
history->session.sess_curr = g_list_first(history->session.items);
|
||||
history->session.orig_curr = g_list_first(history->items);
|
||||
}
|
||||
}
|
||||
|
||||
static void _session_next(PHistory history)
|
||||
{
|
||||
history->session.sess_curr = g_list_next(history->session.sess_curr);
|
||||
history->session.orig_curr = g_list_next(history->session.orig_curr);
|
||||
|
||||
if (history->session.sess_curr == NULL) {
|
||||
history->session.sess_curr = g_list_last(history->session.items);
|
||||
history->session.orig_curr = NULL;
|
||||
}
|
||||
}
|
||||
33
src/prof_history.h
Normal file
33
src/prof_history.h
Normal file
@@ -0,0 +1,33 @@
|
||||
/*
|
||||
* prof_history.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROF_HISTORY_H
|
||||
#define PROF_HISTORY_H
|
||||
|
||||
typedef struct p_history_t *PHistory;
|
||||
|
||||
PHistory p_history_new(unsigned int size);
|
||||
char * p_history_previous(PHistory history, char *item);
|
||||
char * p_history_next(PHistory history, char *item);
|
||||
void p_history_append(PHistory history, char *item);
|
||||
|
||||
#endif
|
||||
82
src/profanity.c
Normal file
82
src/profanity.c
Normal file
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* profanity.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <glib.h>
|
||||
|
||||
#include "profanity.h"
|
||||
#include "log.h"
|
||||
#include "ui.h"
|
||||
#include "jabber.h"
|
||||
#include "command.h"
|
||||
#include "preferences.h"
|
||||
#include "contact_list.h"
|
||||
|
||||
static void _profanity_shutdown(void);
|
||||
|
||||
void profanity_run(void)
|
||||
{
|
||||
gboolean cmd_result = TRUE;
|
||||
|
||||
inp_non_block();
|
||||
while(cmd_result == TRUE) {
|
||||
int ch = ERR;
|
||||
char inp[200];
|
||||
int size = 0;
|
||||
|
||||
while(ch != '\n') {
|
||||
win_handle_special_keys(&ch);
|
||||
|
||||
if (ch == KEY_RESIZE) {
|
||||
gui_resize(ch, inp, size);
|
||||
}
|
||||
|
||||
gui_refresh();
|
||||
jabber_process_events();
|
||||
|
||||
inp_get_char(&ch, inp, &size);
|
||||
}
|
||||
|
||||
inp[size++] = '\0';
|
||||
cmd_result = process_input(inp);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void profanity_init(const int disable_tls)
|
||||
{
|
||||
log_init();
|
||||
prefs_load();
|
||||
gui_init();
|
||||
jabber_init(disable_tls);
|
||||
command_init();
|
||||
contact_list_init();
|
||||
atexit(_profanity_shutdown);
|
||||
}
|
||||
|
||||
void _profanity_shutdown(void)
|
||||
{
|
||||
jabber_disconnect();
|
||||
gui_close();
|
||||
log_close();
|
||||
}
|
||||
30
src/profanity.h
Normal file
30
src/profanity.h
Normal file
@@ -0,0 +1,30 @@
|
||||
/*
|
||||
* profanity.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef PROFANITY_H
|
||||
#define PROFANITY_H
|
||||
|
||||
void profanity_init(const int disable_tls);
|
||||
void profanity_run(void);
|
||||
void profanity_shutdown(void);
|
||||
|
||||
#endif
|
||||
224
src/status_bar.c
Normal file
224
src/status_bar.c
Normal file
@@ -0,0 +1,224 @@
|
||||
/*
|
||||
* status_bar.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
|
||||
static WINDOW *status_bar;
|
||||
static char *message = NULL;
|
||||
static char _active[29] = "[ ][ ][ ][ ][ ][ ][ ][ ][ ]";
|
||||
static int is_active[9];
|
||||
static int is_new[9];
|
||||
static int dirty;
|
||||
static char curr_time[80];
|
||||
|
||||
static void _status_bar_update_time(void);
|
||||
|
||||
void create_status_bar(void)
|
||||
{
|
||||
int rows, cols, i;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
for (i = 0; i < 9; i++) {
|
||||
is_active[i] = FALSE;
|
||||
is_new[i] = FALSE;
|
||||
}
|
||||
|
||||
status_bar = newwin(1, cols, rows-2, 0);
|
||||
wbkgd(status_bar, COLOR_PAIR(8));
|
||||
wattron(status_bar, COLOR_PAIR(4));
|
||||
mvwprintw(status_bar, 0, cols - 29, _active);
|
||||
wattroff(status_bar, COLOR_PAIR(4));
|
||||
|
||||
get_time(curr_time);
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_refresh(void)
|
||||
{
|
||||
char new_time[80];
|
||||
get_time(new_time);
|
||||
|
||||
if (strcmp(new_time, curr_time) != 0) {
|
||||
dirty = TRUE;
|
||||
strcpy(curr_time, new_time);
|
||||
}
|
||||
|
||||
if (dirty) {
|
||||
_status_bar_update_time();
|
||||
wrefresh(status_bar);
|
||||
inp_put_back();
|
||||
dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void status_bar_resize(void)
|
||||
{
|
||||
int rows, cols, i;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
mvwin(status_bar, rows-2, 0);
|
||||
wresize(status_bar, 1, cols);
|
||||
wbkgd(status_bar, COLOR_PAIR(8));
|
||||
wclear(status_bar);
|
||||
wattron(status_bar, COLOR_PAIR(4));
|
||||
mvwprintw(status_bar, 0, cols - 29, _active);
|
||||
wattroff(status_bar, COLOR_PAIR(4));
|
||||
|
||||
for(i = 0; i < 9; i++) {
|
||||
if (is_new[i])
|
||||
status_bar_new(i+1);
|
||||
else if (is_active[i])
|
||||
status_bar_active(i+1);
|
||||
}
|
||||
|
||||
if (message != NULL)
|
||||
mvwprintw(status_bar, 0, 9, message);
|
||||
|
||||
get_time(curr_time);
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_inactive(const int win)
|
||||
{
|
||||
is_active[win-1] = FALSE;
|
||||
is_new[win-1] = FALSE;
|
||||
|
||||
int active_pos = 1 + ((win -1) * 3);
|
||||
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
mvwaddch(status_bar, 0, cols - 29 + active_pos, ' ');
|
||||
if (win == 9)
|
||||
mvwaddch(status_bar, 0, cols - 29 + active_pos + 1, ' ');
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_active(const int win)
|
||||
{
|
||||
is_active[win-1] = TRUE;
|
||||
is_new[win-1] = FALSE;
|
||||
|
||||
int active_pos = 1 + ((win -1) * 3);
|
||||
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
wattron(status_bar, COLOR_PAIR(4));
|
||||
if (win < 9)
|
||||
mvwprintw(status_bar, 0, cols - 29 + active_pos, "%d", win+1);
|
||||
else
|
||||
mvwprintw(status_bar, 0, cols - 29 + active_pos, "10");
|
||||
wattroff(status_bar, COLOR_PAIR(4));
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_new(const int win)
|
||||
{
|
||||
is_active[win-1] = TRUE;
|
||||
is_new[win-1] = TRUE;
|
||||
|
||||
int active_pos = 1 + ((win -1) * 3);
|
||||
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
wattron(status_bar, COLOR_PAIR(3));
|
||||
wattron(status_bar, A_BLINK);
|
||||
if (win < 9)
|
||||
mvwprintw(status_bar, 0, cols - 29 + active_pos, "%d", win+1);
|
||||
else
|
||||
mvwprintw(status_bar, 0, cols - 29 + active_pos, "10");
|
||||
wattroff(status_bar, COLOR_PAIR(3));
|
||||
wattroff(status_bar, A_BLINK);
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_get_password(void)
|
||||
{
|
||||
status_bar_print_message("Enter password:");
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_print_message(const char * const msg)
|
||||
{
|
||||
if (message != NULL)
|
||||
free(message);
|
||||
|
||||
message = (char *) malloc((strlen(msg) + 1) * sizeof(char));
|
||||
strcpy(message, msg);
|
||||
mvwprintw(status_bar, 0, 9, message);
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void status_bar_clear(void)
|
||||
{
|
||||
if (message != NULL) {
|
||||
free(message);
|
||||
message = NULL;
|
||||
}
|
||||
|
||||
int i;
|
||||
for (i = 0; i < 9; i++) {
|
||||
is_active[i] = FALSE;
|
||||
is_new[i] = FALSE;
|
||||
}
|
||||
|
||||
wclear(status_bar);
|
||||
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
wattron(status_bar, COLOR_PAIR(4));
|
||||
mvwprintw(status_bar, 0, cols - 29, _active);
|
||||
wattroff(status_bar, COLOR_PAIR(4));
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
static void _status_bar_update_time(void)
|
||||
{
|
||||
char bar_time[6];
|
||||
char tstmp[80];
|
||||
get_time(tstmp);
|
||||
sprintf(bar_time, "%s", tstmp);
|
||||
|
||||
wattron(status_bar, COLOR_PAIR(4));
|
||||
mvwaddch(status_bar, 0, 1, '[');
|
||||
wattroff(status_bar, COLOR_PAIR(4));
|
||||
mvwprintw(status_bar, 0, 2, bar_time);
|
||||
wattron(status_bar, COLOR_PAIR(4));
|
||||
mvwaddch(status_bar, 0, 7, ']');
|
||||
wattroff(status_bar, COLOR_PAIR(4));
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
134
src/title_bar.c
Normal file
134
src/title_bar.c
Normal file
@@ -0,0 +1,134 @@
|
||||
/*
|
||||
* title_bar.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "ui.h"
|
||||
|
||||
static WINDOW *title_bar;
|
||||
static char *current_title = NULL;
|
||||
static int dirty;
|
||||
static jabber_presence_t current_status;
|
||||
|
||||
static void _title_bar_draw_title(void);
|
||||
static void _title_bar_draw_status(void);
|
||||
|
||||
void create_title_bar(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
title_bar = newwin(1, cols, 0, 0);
|
||||
wbkgd(title_bar, COLOR_PAIR(8));
|
||||
title_bar_title();
|
||||
title_bar_set_status(PRESENCE_OFFLINE);
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void title_bar_title(void)
|
||||
{
|
||||
title_bar_show("Profanity. Type /help for help information.");
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void title_bar_resize(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
wresize(title_bar, 1, cols);
|
||||
wbkgd(title_bar, COLOR_PAIR(8));
|
||||
wclear(title_bar);
|
||||
_title_bar_draw_title();
|
||||
_title_bar_draw_status();
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void title_bar_refresh(void)
|
||||
{
|
||||
if (dirty) {
|
||||
wrefresh(title_bar);
|
||||
inp_put_back();
|
||||
dirty = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
void title_bar_show(const char * const title)
|
||||
{
|
||||
if (current_title != NULL)
|
||||
free(current_title);
|
||||
|
||||
current_title = (char *) malloc((strlen(title) + 1) * sizeof(char));
|
||||
strcpy(current_title, title);
|
||||
_title_bar_draw_title();
|
||||
}
|
||||
|
||||
void title_bar_set_status(jabber_presence_t status)
|
||||
{
|
||||
current_status = status;
|
||||
_title_bar_draw_status();
|
||||
}
|
||||
|
||||
static void _title_bar_draw_status()
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
wattron(title_bar, COLOR_PAIR(4));
|
||||
mvwaddch(title_bar, 0, cols - 14, '[');
|
||||
wattroff(title_bar, COLOR_PAIR(4));
|
||||
|
||||
if (current_status == PRESENCE_ONLINE) {
|
||||
mvwprintw(title_bar, 0, cols - 13, " ...online ");
|
||||
} else if (current_status == PRESENCE_AWAY) {
|
||||
mvwprintw(title_bar, 0, cols - 13, " .....away ");
|
||||
} else if (current_status == PRESENCE_DND) {
|
||||
mvwprintw(title_bar, 0, cols - 13, " ......dnd ");
|
||||
} else if (current_status == PRESENCE_CHAT) {
|
||||
mvwprintw(title_bar, 0, cols - 13, " .....chat ");
|
||||
} else if (current_status == PRESENCE_XA) {
|
||||
mvwprintw(title_bar, 0, cols - 13, " .......xa ");
|
||||
} else {
|
||||
mvwprintw(title_bar, 0, cols - 13, " ..offline ");
|
||||
}
|
||||
|
||||
wattron(title_bar, COLOR_PAIR(4));
|
||||
mvwaddch(title_bar, 0, cols - 2, ']');
|
||||
wattroff(title_bar, COLOR_PAIR(4));
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
static void _title_bar_draw_title(void)
|
||||
{
|
||||
wmove(title_bar, 0, 0);
|
||||
int i;
|
||||
for (i = 0; i < 45; i++)
|
||||
waddch(title_bar, ' ');
|
||||
mvwprintw(title_bar, 0, 0, " %s", current_title);
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
100
src/ui.h
Normal file
100
src/ui.h
Normal file
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* ui.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef WINDOWS_H
|
||||
#define WINDOWS_h
|
||||
|
||||
#include <ncurses.h>
|
||||
|
||||
#include "common.h"
|
||||
#include "contact_list.h"
|
||||
|
||||
struct prof_win {
|
||||
char from[100];
|
||||
WINDOW *win;
|
||||
int y_pos;
|
||||
int paged;
|
||||
};
|
||||
|
||||
// gui startup and shutdown, resize
|
||||
void gui_init(void);
|
||||
void gui_refresh(void);
|
||||
void gui_close(void);
|
||||
void gui_resize(const int ch, const char * const input,
|
||||
const int size);
|
||||
|
||||
// create windows
|
||||
void create_title_bar(void);
|
||||
void create_status_bar(void);
|
||||
void create_input_window(void);
|
||||
|
||||
// title bar actions
|
||||
void title_bar_refresh(void);
|
||||
void title_bar_resize(void);
|
||||
void title_bar_show(const char * const title);
|
||||
void title_bar_title(void);
|
||||
void title_bar_set_status(jabber_presence_t status);
|
||||
|
||||
// main window actions
|
||||
int win_close_win(void);
|
||||
int win_in_chat(void);
|
||||
char *win_get_recipient(void);
|
||||
void win_show_incomming_msg(const char * const from, const char * const message);
|
||||
void win_show_outgoing_msg(const char * const from, const char * const to,
|
||||
const char * const message);
|
||||
void win_handle_special_keys(const int * const ch);
|
||||
void win_page_off(void);
|
||||
void win_contact_online(const char * const from, const char * const show,
|
||||
const char * const status);
|
||||
void win_contact_offline(const char * const from, const char * const show,
|
||||
const char * const status);
|
||||
void win_disconnected(void);
|
||||
|
||||
// console window actions
|
||||
void cons_help(void);
|
||||
void cons_bad_command(const char * const cmd);
|
||||
void cons_show(const char * const cmd);
|
||||
void cons_bad_show(const char * const cmd);
|
||||
void cons_highlight_show(const char * const cmd);
|
||||
void cons_show_online_contacts(GSList * list);
|
||||
|
||||
// status bar actions
|
||||
void status_bar_refresh(void);
|
||||
void status_bar_resize(void);
|
||||
void status_bar_clear(void);
|
||||
void status_bar_get_password(void);
|
||||
void status_bar_print_message(const char * const msg);
|
||||
void status_bar_inactive(const int win);
|
||||
void status_bar_active(const int win);
|
||||
void status_bar_new(const int win);
|
||||
void status_bar_update_time(void);
|
||||
|
||||
// input window actions
|
||||
void inp_get_char(int *ch, char *input, int *size);
|
||||
void inp_clear(void);
|
||||
void inp_win_resize(const char * input, const int size);
|
||||
void inp_put_back(void);
|
||||
void inp_non_block(void);
|
||||
void inp_block(void);
|
||||
void inp_get_password(char *passwd);
|
||||
|
||||
#endif
|
||||
91
src/util.c
Normal file
91
src/util.c
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* util.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <time.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
void get_time(char *thetime)
|
||||
{
|
||||
time_t rawtime;
|
||||
struct tm *timeinfo;
|
||||
|
||||
time(&rawtime);
|
||||
timeinfo = localtime(&rawtime);
|
||||
|
||||
strftime(thetime, 80, "%H:%M", timeinfo);
|
||||
}
|
||||
|
||||
char * str_replace (const char *string, const char *substr,
|
||||
const char *replacement) {
|
||||
char *tok = NULL;
|
||||
char *newstr = NULL;
|
||||
char *oldstr = NULL;
|
||||
char *head = NULL;
|
||||
|
||||
if (string == NULL)
|
||||
return NULL;
|
||||
|
||||
if ( substr == NULL ||
|
||||
replacement == NULL ||
|
||||
(strcmp(substr, "") == 0))
|
||||
return strdup (string);
|
||||
|
||||
newstr = strdup (string);
|
||||
head = newstr;
|
||||
|
||||
while ( (tok = strstr ( head, substr ))) {
|
||||
oldstr = newstr;
|
||||
newstr = malloc ( strlen ( oldstr ) - strlen ( substr ) +
|
||||
strlen ( replacement ) + 1 );
|
||||
|
||||
if ( newstr == NULL ) {
|
||||
free (oldstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
memcpy ( newstr, oldstr, tok - oldstr );
|
||||
memcpy ( newstr + (tok - oldstr), replacement, strlen ( replacement ) );
|
||||
memcpy ( newstr + (tok - oldstr) + strlen( replacement ),
|
||||
tok + strlen ( substr ),
|
||||
strlen ( oldstr ) - strlen ( substr ) - ( tok - oldstr ) );
|
||||
memset ( newstr + strlen ( oldstr ) - strlen ( substr ) +
|
||||
strlen ( replacement ) , 0, 1 );
|
||||
|
||||
head = newstr + (tok - oldstr) + strlen( replacement );
|
||||
free (oldstr);
|
||||
}
|
||||
|
||||
return newstr;
|
||||
}
|
||||
|
||||
int str_contains(char str[], int size, char ch)
|
||||
{
|
||||
int i;
|
||||
for (i = 0; i < size; i++) {
|
||||
if (str[i] == ch)
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
31
src/util.h
Normal file
31
src/util.h
Normal file
@@ -0,0 +1,31 @@
|
||||
/*
|
||||
* util.h
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef UTIL_H
|
||||
#define UTIL_H
|
||||
|
||||
void get_time(char *thetime);
|
||||
char * str_replace(const char *string, const char *substr,
|
||||
const char *replacement);
|
||||
int str_contains(char str[], int size, char ch);
|
||||
|
||||
#endif
|
||||
665
src/windows.c
Normal file
665
src/windows.c
Normal file
@@ -0,0 +1,665 @@
|
||||
/*
|
||||
* windows.c
|
||||
*
|
||||
* Copyright (C) 2012 James Booth <boothj5@gmail.com>
|
||||
*
|
||||
* This file is part of Profanity.
|
||||
*
|
||||
* Profanity is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Profanity is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Profanity. If not, see <http://www.gnu.org/licenses/>.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <ncurses.h>
|
||||
#include <glib.h>
|
||||
#include <libnotify/notify.h>
|
||||
|
||||
#include "ui.h"
|
||||
#include "util.h"
|
||||
#include "contact.h"
|
||||
#include "preferences.h"
|
||||
|
||||
#define CONS_WIN_TITLE "_cons"
|
||||
#define PAD_SIZE 200
|
||||
#define NUM_WINS 10
|
||||
|
||||
// holds console at index 0 and chat wins 1 through to 9
|
||||
static struct prof_win _wins[NUM_WINS];
|
||||
|
||||
// the window currently being displayed
|
||||
static int _curr_prof_win = 0;
|
||||
|
||||
// shortcut pointer to console window
|
||||
static WINDOW * _cons_win = NULL;
|
||||
|
||||
// current window state
|
||||
static int dirty;
|
||||
|
||||
// max columns for main windows, never resize below
|
||||
static int max_cols = 0;
|
||||
|
||||
static void _create_windows(void);
|
||||
static void _print_splash_logo(WINDOW *win);
|
||||
static int _find_prof_win_index(const char * const contact);
|
||||
static int _new_prof_win(const char * const contact);
|
||||
static void _current_window_refresh(void);
|
||||
static void _win_switch_if_active(const int i);
|
||||
static void _win_show_time(WINDOW *win);
|
||||
static void _win_show_user(WINDOW *win, const char * const user, const int colour);
|
||||
static void _win_show_message(WINDOW *win, const char * const message);
|
||||
static void _show_status_string(WINDOW *win, const char * const from,
|
||||
const char * const show, const char * const status, const char * const pre,
|
||||
const char * const default_show);
|
||||
static void _cons_show_incoming_message(const char * const short_from,
|
||||
const int win_index);
|
||||
static void _win_handle_switch(const int * const ch);
|
||||
static void _win_handle_page(const int * const ch);
|
||||
static void _win_resize_all(void);
|
||||
static void _win_notify(char * short_from);
|
||||
|
||||
void gui_init(void)
|
||||
{
|
||||
initscr();
|
||||
cbreak();
|
||||
keypad(stdscr, TRUE);
|
||||
|
||||
if (has_colors()) {
|
||||
use_default_colors();
|
||||
start_color();
|
||||
|
||||
init_pair(1, prefs_get_text(), prefs_get_bkgnd());
|
||||
init_pair(2, prefs_get_online(), prefs_get_bkgnd());
|
||||
init_pair(3, prefs_get_text(), prefs_get_bar());
|
||||
init_pair(4, prefs_get_bar_draw(), prefs_get_bar());
|
||||
init_pair(5, prefs_get_offline(), prefs_get_bkgnd());
|
||||
init_pair(6, prefs_get_err(), prefs_get_bkgnd());
|
||||
init_pair(7, prefs_get_inc(), prefs_get_bkgnd());
|
||||
init_pair(8, prefs_get_bar_text(), prefs_get_bar());
|
||||
}
|
||||
|
||||
refresh();
|
||||
|
||||
create_title_bar();
|
||||
create_status_bar();
|
||||
create_input_window();
|
||||
_create_windows();
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void gui_refresh(void)
|
||||
{
|
||||
title_bar_refresh();
|
||||
status_bar_refresh();
|
||||
|
||||
if (dirty) {
|
||||
_current_window_refresh();
|
||||
dirty = FALSE;
|
||||
}
|
||||
|
||||
inp_put_back();
|
||||
}
|
||||
|
||||
void gui_close(void)
|
||||
{
|
||||
endwin();
|
||||
}
|
||||
|
||||
void gui_resize(const int ch, const char * const input, const int size)
|
||||
{
|
||||
title_bar_resize();
|
||||
status_bar_resize();
|
||||
_win_resize_all();
|
||||
inp_win_resize(input, size);
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
int win_close_win(void)
|
||||
{
|
||||
if (win_in_chat()) {
|
||||
// reset the chat win to unused
|
||||
strcpy(_wins[_curr_prof_win].from, "");
|
||||
wclear(_wins[_curr_prof_win].win);
|
||||
|
||||
// set it as inactive in the status bar
|
||||
status_bar_inactive(_curr_prof_win);
|
||||
|
||||
// go back to console window
|
||||
_curr_prof_win = 0;
|
||||
title_bar_title();
|
||||
|
||||
dirty = TRUE;
|
||||
|
||||
// success
|
||||
return 1;
|
||||
} else {
|
||||
// didn't close anything
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
int win_in_chat(void)
|
||||
{
|
||||
return ((_curr_prof_win != 0) &&
|
||||
(strcmp(_wins[_curr_prof_win].from, "") != 0));
|
||||
}
|
||||
|
||||
char *win_get_recipient(void)
|
||||
{
|
||||
struct prof_win current = _wins[_curr_prof_win];
|
||||
char *recipient = (char *) malloc(sizeof(char) * (strlen(current.from) + 1));
|
||||
strcpy(recipient, current.from);
|
||||
return recipient;
|
||||
}
|
||||
|
||||
void win_show_incomming_msg(const char * const from, const char * const message)
|
||||
{
|
||||
char from_cpy[strlen(from) + 1];
|
||||
strcpy(from_cpy, from);
|
||||
char *short_from = strtok(from_cpy, "/");
|
||||
|
||||
int win_index = _find_prof_win_index(short_from);
|
||||
if (win_index == NUM_WINS)
|
||||
win_index = _new_prof_win(short_from);
|
||||
|
||||
WINDOW *win = _wins[win_index].win;
|
||||
_win_show_time(win);
|
||||
_win_show_user(win, short_from, 1);
|
||||
_win_show_message(win, message);
|
||||
|
||||
if (win_index == _curr_prof_win) {
|
||||
status_bar_active(win_index);
|
||||
dirty = TRUE;
|
||||
} else {
|
||||
status_bar_new(win_index);
|
||||
_cons_show_incoming_message(short_from, win_index);
|
||||
if (prefs_get_flash())
|
||||
flash();
|
||||
|
||||
}
|
||||
|
||||
if (prefs_get_beep())
|
||||
beep();
|
||||
if (prefs_get_notify())
|
||||
_win_notify(short_from);
|
||||
}
|
||||
|
||||
static void _win_notify(char * short_from)
|
||||
{
|
||||
notify_init("Profanity");
|
||||
|
||||
// create a new notification
|
||||
NotifyNotification *incoming;
|
||||
incoming = notify_notification_new("Profanity", short_from, NULL);
|
||||
|
||||
// set the timeout of the notification to 10 secs
|
||||
notify_notification_set_timeout(incoming, 10000);
|
||||
|
||||
// set the category so as to tell what kind it is
|
||||
char category[30] = "Incoming message";
|
||||
notify_notification_set_category(incoming, category);
|
||||
|
||||
// set the urgency level of the notification
|
||||
notify_notification_set_urgency(incoming, NOTIFY_URGENCY_NORMAL);
|
||||
|
||||
GError *error = NULL;
|
||||
notify_notification_show(incoming, &error);
|
||||
}
|
||||
|
||||
void win_show_outgoing_msg(const char * const from, const char * const to,
|
||||
const char * const message)
|
||||
{
|
||||
int win_index = _find_prof_win_index(to);
|
||||
if (win_index == NUM_WINS)
|
||||
win_index = _new_prof_win(to);
|
||||
|
||||
WINDOW *win = _wins[win_index].win;
|
||||
_win_show_time(win);
|
||||
_win_show_user(win, from, 0);
|
||||
_win_show_message(win, message);
|
||||
|
||||
status_bar_active(win_index);
|
||||
|
||||
if (win_index == _curr_prof_win) {
|
||||
dirty = TRUE;
|
||||
} else {
|
||||
status_bar_new(win_index);
|
||||
}
|
||||
}
|
||||
|
||||
void win_contact_online(const char * const from, const char * const show,
|
||||
const char * const status)
|
||||
{
|
||||
_show_status_string(_cons_win, from, show, status, "++", "online");
|
||||
|
||||
int win_index = _find_prof_win_index(from);
|
||||
if (win_index != NUM_WINS) {
|
||||
WINDOW *win = _wins[win_index].win;
|
||||
_show_status_string(win, from, show, status, "++", "online");
|
||||
}
|
||||
|
||||
if (win_index == _curr_prof_win)
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void win_contact_offline(const char * const from, const char * const show,
|
||||
const char * const status)
|
||||
{
|
||||
_show_status_string(_cons_win, from, show, status, "--", "offline");
|
||||
|
||||
int win_index = _find_prof_win_index(from);
|
||||
if (win_index != NUM_WINS) {
|
||||
WINDOW *win = _wins[win_index].win;
|
||||
_show_status_string(win, from, show, status, "--", "offline");
|
||||
}
|
||||
|
||||
if (win_index == _curr_prof_win)
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void win_disconnected(void)
|
||||
{
|
||||
int i;
|
||||
// show message in all active chats
|
||||
for (i = 1; i < NUM_WINS; i++) {
|
||||
if (strcmp(_wins[i].from, "") != 0) {
|
||||
WINDOW *win = _wins[_curr_prof_win].win;
|
||||
_win_show_time(win);
|
||||
wattron(win, COLOR_PAIR(6));
|
||||
wprintw(win, "%s\n", "Lost connection.");
|
||||
wattroff(win, COLOR_PAIR(6));
|
||||
|
||||
// if current win, set dirty
|
||||
if (i == _curr_prof_win) {
|
||||
dirty = TRUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void cons_help(void)
|
||||
{
|
||||
cons_show("");
|
||||
cons_show("Basic Commands:");
|
||||
cons_show("");
|
||||
cons_show("/help : This help.");
|
||||
cons_show("/connect user@host : Login to jabber.");
|
||||
cons_show("/msg user@host mesg : Send mesg to user.");
|
||||
cons_show("/close : Close a chat window.");
|
||||
cons_show("/who : Find out who is online.");
|
||||
cons_show("/ros : List all contacts.");
|
||||
cons_show("/quit : Quit Profanity.");
|
||||
cons_show("");
|
||||
cons_show("Settings:");
|
||||
cons_show("");
|
||||
cons_show("/beep <on/off> : Enable/disable sound notification");
|
||||
cons_show("/notify <on/off> : Enable/disable desktop notifications");
|
||||
cons_show("/flash <on/off> : Enable/disable screen flash notification");
|
||||
cons_show("/showsplash <on/off> : Enable/disable splash logo on startup");
|
||||
cons_show("");
|
||||
cons_show("Status changes (msg is optional):");
|
||||
cons_show("");
|
||||
cons_show("/away <msg> : Set status to away.");
|
||||
cons_show("/online <msg> : Set status to online.");
|
||||
cons_show("/dnd <msg> : Set status to dnd (do not disturb).");
|
||||
cons_show("/chat <msg> : Set status to chat (available for chat).");
|
||||
cons_show("/xa <msg> : Set status to xa (extended away).");
|
||||
cons_show("");
|
||||
cons_show("Navigation:");
|
||||
cons_show("");
|
||||
cons_show("F1 : This console window.");
|
||||
cons_show("F2-F10 : Chat windows.");
|
||||
cons_show("UP, DOWN : Navigate input history.");
|
||||
cons_show("LEFT, RIGHT : Edit current input.");
|
||||
cons_show("TAB : Autocomplete command/recipient/login");
|
||||
cons_show("PAGE UP, PAGE DOWN : Page the chat window.");
|
||||
cons_show("");
|
||||
|
||||
if (_curr_prof_win == 0)
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void cons_show_online_contacts(GSList *list)
|
||||
{
|
||||
_win_show_time(_cons_win);
|
||||
wprintw(_cons_win, "Online contacts:\n");
|
||||
|
||||
GSList *curr = list;
|
||||
|
||||
while(curr) {
|
||||
PContact contact = curr->data;
|
||||
_win_show_time(_cons_win);
|
||||
wattron(_cons_win, COLOR_PAIR(2));
|
||||
wprintw(_cons_win, "%s", p_contact_name(contact));
|
||||
if (p_contact_show(contact))
|
||||
wprintw(_cons_win, " is %s", p_contact_show(contact));
|
||||
if (p_contact_status(contact))
|
||||
wprintw(_cons_win, ", \"%s\"", p_contact_status(contact));
|
||||
wprintw(_cons_win, "\n");
|
||||
wattroff(_cons_win, COLOR_PAIR(2));
|
||||
|
||||
curr = g_slist_next(curr);
|
||||
}
|
||||
}
|
||||
|
||||
void cons_bad_show(const char * const msg)
|
||||
{
|
||||
_win_show_time(_cons_win);
|
||||
wattron(_cons_win, COLOR_PAIR(6));
|
||||
wprintw(_cons_win, "%s\n", msg);
|
||||
wattroff(_cons_win, COLOR_PAIR(6));
|
||||
|
||||
if (_curr_prof_win == 0)
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void cons_show(const char * const msg)
|
||||
{
|
||||
_win_show_time(_cons_win);
|
||||
wprintw(_cons_win, "%s\n", msg);
|
||||
|
||||
if (_curr_prof_win == 0)
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void cons_bad_command(const char * const cmd)
|
||||
{
|
||||
_win_show_time(_cons_win);
|
||||
wprintw(_cons_win, "Unknown command: %s\n", cmd);
|
||||
|
||||
if (_curr_prof_win == 0)
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
void win_handle_special_keys(const int * const ch)
|
||||
{
|
||||
_win_handle_switch(ch);
|
||||
_win_handle_page(ch);
|
||||
}
|
||||
|
||||
void win_page_off(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
_wins[_curr_prof_win].paged = 0;
|
||||
|
||||
int y, x;
|
||||
getyx(_wins[_curr_prof_win].win, y, x);
|
||||
|
||||
int size = rows - 3;
|
||||
|
||||
_wins[_curr_prof_win].y_pos = y - (size - 1);
|
||||
if (_wins[_curr_prof_win].y_pos < 0)
|
||||
_wins[_curr_prof_win].y_pos = 0;
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
static void _create_windows(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
max_cols = cols;
|
||||
|
||||
// create the console window in 0
|
||||
struct prof_win cons;
|
||||
strcpy(cons.from, CONS_WIN_TITLE);
|
||||
cons.win = newpad(PAD_SIZE, cols);
|
||||
wbkgd(cons.win, COLOR_PAIR(1));
|
||||
cons.y_pos = 0;
|
||||
cons.paged = 0;
|
||||
scrollok(cons.win, TRUE);
|
||||
|
||||
_wins[0] = cons;
|
||||
_cons_win = _wins[0].win;
|
||||
|
||||
// wattrset(_cons_win, A_BOLD);
|
||||
_win_show_time(_cons_win);
|
||||
if (prefs_get_showsplash()) {
|
||||
_print_splash_logo(_cons_win);
|
||||
} else {
|
||||
wprintw(_cons_win, "Welcome to Profanity.\n");
|
||||
}
|
||||
prefresh(_cons_win, 0, 0, 1, 0, rows-3, cols-1);
|
||||
|
||||
dirty = TRUE;
|
||||
|
||||
// create the chat windows
|
||||
int i;
|
||||
for (i = 1; i < NUM_WINS; i++) {
|
||||
struct prof_win chat;
|
||||
strcpy(chat.from, "");
|
||||
chat.win = newpad(PAD_SIZE, cols);
|
||||
wbkgd(chat.win, COLOR_PAIR(1));
|
||||
chat.y_pos = 0;
|
||||
chat.paged = 0;
|
||||
// wattrset(chat.win, A_BOLD);
|
||||
scrollok(chat.win, TRUE);
|
||||
_wins[i] = chat;
|
||||
}
|
||||
}
|
||||
|
||||
static void _print_splash_logo(WINDOW *win)
|
||||
{
|
||||
wprintw(win, "Welcome to\n");
|
||||
wattron(win, COLOR_PAIR(5));
|
||||
wprintw(win, " ___ _ \n");
|
||||
wprintw(win, " / __) (_)_ \n");
|
||||
wprintw(win, " ____ ____ ___ | |__ ____ ____ _| |_ _ _ \n");
|
||||
wprintw(win, "| _ \\ / ___) _ \\| __) _ | _ \\| | _) | | |\n");
|
||||
wprintw(win, "| | | | | | |_| | | ( ( | | | | | | |_| |_| |\n");
|
||||
wprintw(win, "| ||_/|_| \\___/|_| \\_||_|_| |_|_|\\___)__ |\n");
|
||||
wprintw(win, "|_| (____/ \n");
|
||||
wattroff(win, COLOR_PAIR(5));
|
||||
}
|
||||
|
||||
static int _find_prof_win_index(const char * const contact)
|
||||
{
|
||||
// find the chat window for recipient
|
||||
int i;
|
||||
for (i = 1; i < NUM_WINS; i++)
|
||||
if (strcmp(_wins[i].from, contact) == 0)
|
||||
break;
|
||||
|
||||
return i;
|
||||
}
|
||||
|
||||
static int _new_prof_win(const char * const contact)
|
||||
{
|
||||
int i;
|
||||
// find the first unused one
|
||||
for (i = 1; i < NUM_WINS; i++)
|
||||
if (strcmp(_wins[i].from, "") == 0)
|
||||
break;
|
||||
|
||||
// set it up
|
||||
strcpy(_wins[i].from, contact);
|
||||
wclear(_wins[i].win);
|
||||
|
||||
return i;
|
||||
}
|
||||
static void _win_switch_if_active(const int i)
|
||||
{
|
||||
win_page_off();
|
||||
if (strcmp(_wins[i].from, "") != 0) {
|
||||
_curr_prof_win = i;
|
||||
win_page_off();
|
||||
|
||||
if (i == 0) {
|
||||
title_bar_title();
|
||||
} else {
|
||||
title_bar_show(_wins[i].from);
|
||||
status_bar_active(i);
|
||||
}
|
||||
}
|
||||
|
||||
dirty = TRUE;
|
||||
}
|
||||
|
||||
static void _win_show_time(WINDOW *win)
|
||||
{
|
||||
char tstmp[80];
|
||||
get_time(tstmp);
|
||||
wprintw(win, "%s - ", tstmp);
|
||||
}
|
||||
|
||||
static void _win_show_user(WINDOW *win, const char * const user, const int colour)
|
||||
{
|
||||
if (colour)
|
||||
wattron(win, COLOR_PAIR(2));
|
||||
wprintw(win, "%s: ", user);
|
||||
if (colour)
|
||||
wattroff(win, COLOR_PAIR(2));
|
||||
}
|
||||
|
||||
static void _win_show_message(WINDOW *win, const char * const message)
|
||||
{
|
||||
// wattroff(win, A_BOLD);
|
||||
wprintw(win, "%s\n", message);
|
||||
// wattron(win, A_BOLD);
|
||||
}
|
||||
|
||||
static void _current_window_refresh(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
WINDOW *current = _wins[_curr_prof_win].win;
|
||||
prefresh(current, _wins[_curr_prof_win].y_pos, 0, 1, 0, rows-3, cols-1);
|
||||
}
|
||||
|
||||
void _win_resize_all(void)
|
||||
{
|
||||
int rows, cols;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
|
||||
// only make the pads bigger, to avoid data loss on cropping
|
||||
if (cols > max_cols) {
|
||||
max_cols = cols;
|
||||
|
||||
int i;
|
||||
for (i = 0; i < NUM_WINS; i++) {
|
||||
wresize(_wins[i].win, PAD_SIZE, cols);
|
||||
}
|
||||
}
|
||||
|
||||
WINDOW *current = _wins[_curr_prof_win].win;
|
||||
prefresh(current, _wins[_curr_prof_win].y_pos, 0, 1, 0, rows-3, cols-1);
|
||||
}
|
||||
|
||||
static void _show_status_string(WINDOW *win, const char * const from,
|
||||
const char * const show, const char * const status, const char * const pre,
|
||||
const char * const default_show)
|
||||
{
|
||||
_win_show_time(win);
|
||||
if (strcmp(default_show, "online") == 0) {
|
||||
wattron(win, COLOR_PAIR(2));
|
||||
} else {
|
||||
wattron(win, COLOR_PAIR(5));
|
||||
// wattroff(win, A_BOLD);
|
||||
}
|
||||
|
||||
wprintw(win, "%s %s", pre, from);
|
||||
|
||||
if (show != NULL)
|
||||
wprintw(win, " is %s", show);
|
||||
else
|
||||
wprintw(win, " is %s", default_show);
|
||||
|
||||
if (status != NULL)
|
||||
wprintw(win, ", \"%s\"", status);
|
||||
|
||||
wprintw(win, "\n");
|
||||
|
||||
if (strcmp(default_show, "online") == 0) {
|
||||
wattroff(win, COLOR_PAIR(2));
|
||||
} else {
|
||||
wattroff(win, COLOR_PAIR(5));
|
||||
// wattron(win, A_BOLD);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void _cons_show_incoming_message(const char * const short_from, const int win_index)
|
||||
{
|
||||
_win_show_time(_cons_win);
|
||||
wattron(_cons_win, COLOR_PAIR(7));
|
||||
wprintw(_cons_win, "<< incoming from %s (%d)\n", short_from, win_index + 1);
|
||||
wattroff(_cons_win, COLOR_PAIR(7));
|
||||
}
|
||||
|
||||
static void _win_handle_switch(const int * const ch)
|
||||
{
|
||||
if (*ch == KEY_F(1)) {
|
||||
_win_switch_if_active(0);
|
||||
} else if (*ch == KEY_F(2)) {
|
||||
_win_switch_if_active(1);
|
||||
} else if (*ch == KEY_F(3)) {
|
||||
_win_switch_if_active(2);
|
||||
} else if (*ch == KEY_F(4)) {
|
||||
_win_switch_if_active(3);
|
||||
} else if (*ch == KEY_F(5)) {
|
||||
_win_switch_if_active(4);
|
||||
} else if (*ch == KEY_F(6)) {
|
||||
_win_switch_if_active(5);
|
||||
} else if (*ch == KEY_F(7)) {
|
||||
_win_switch_if_active(6);
|
||||
} else if (*ch == KEY_F(8)) {
|
||||
_win_switch_if_active(7);
|
||||
} else if (*ch == KEY_F(9)) {
|
||||
_win_switch_if_active(8);
|
||||
} else if (*ch == KEY_F(10)) {
|
||||
_win_switch_if_active(9);
|
||||
}
|
||||
}
|
||||
|
||||
static void _win_handle_page(const int * const ch)
|
||||
{
|
||||
int rows, cols, y, x;
|
||||
getmaxyx(stdscr, rows, cols);
|
||||
getyx(_wins[_curr_prof_win].win, y, x);
|
||||
|
||||
int page_space = rows - 4;
|
||||
int *page_start = &_wins[_curr_prof_win].y_pos;
|
||||
|
||||
// page up
|
||||
if (*ch == KEY_PPAGE) {
|
||||
*page_start -= page_space;
|
||||
|
||||
// went past beginning, show first page
|
||||
if (*page_start < 0)
|
||||
*page_start = 0;
|
||||
|
||||
_wins[_curr_prof_win].paged = 1;
|
||||
dirty = TRUE;
|
||||
|
||||
// page down
|
||||
} else if (*ch == KEY_NPAGE) {
|
||||
*page_start += page_space;
|
||||
|
||||
// only got half a screen, show full screen
|
||||
if ((y - (*page_start)) < page_space)
|
||||
*page_start = y - page_space;
|
||||
|
||||
// went past end, show full screen
|
||||
else if (*page_start >= y)
|
||||
*page_start = y - page_space;
|
||||
|
||||
_wins[_curr_prof_win].paged = 1;
|
||||
dirty = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user