about summary refs log blame commit diff stats
path: root/profanity.c
blob: 98331039dee4e2d4c603efa0e18c2c0f56e552ba (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
pre { line-height: 125%; }
td.linenos .normal { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
span.linenos { color: inherit; background-color: transparent; padding-left: 5px; padding-right: 5px; }
td.linenos .special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
span.linenos.special { color: #000000; background-color: #ffffc0; padding-left: 5px; padding-right: 5px; }
.highlight .hll { background-color: #ffffcc }
.highlight .c { color: #888888 } /* Comment */
.highlight .err { color: #a61717; background-color: #e3d2d2 } /* Error */
.highlight .k { color: #008800; font-weight: bold } /* Keyword */
.highlight .ch { color: #888888 } /* Comment.Hashbang */
.highlight .cm { color: #888888 } /* Comment.Multiline */
.highlight .cp { color: #cc0000; font-weight: bold } /* Comment.Preproc */
.highlight .cpf { color: #888888 } /* Comment.PreprocFile */
.highlight .c1 { color: #888888 } /* Comment.Single */
.highlight .cs { color: #cc0000; font-weight: bold; background-color: #fff0f0 } /* Comment.Special */
.highlight .gd { color: #000000; background-color: #ffdddd } /* Generic.Deleted */
.highlight .ge { font-style: italic } /* Generic.Emph */
.highlight .ges { font-weight: bold; font-style: italic } /* Generic.EmphStrong */
.highlight .gr { color: #aa0000 } /* Generic.Error */
.highlight .gh { color: #333333 } /* Generic.Heading */
.highlight .gi { color: #000000; background-color: #ddffdd } /* Generic.Inserted */
.highlight .go { color: #888888 } /* Generic.Output */
.highlight .gp { color: #555555 } /* Generic.Prompt */
.highlight .gs { font-weight: bold } /* Generic.Strong */
.highlight .gu { color: #666666 } /* Generic.Subheading */
.highlight .gt { color: #aa0000 } /* Generic.Traceback */
.highlight .kc { color: #008800; font-weight: bold } /* Keyword.Constant */
.highlight .kd { color: #008800; font-weight: bold } /* Keyword.Declaration */
.highlight .kn { color: #008800; font-weight: bold } /* Keyword.Namespace */
.highlight .kp { color: #008800 } /* Keyword.Pseudo */
.highlight .kr { color: #008800; font-weight: bold } /* Keyword.Reserved */
.highlight .kt { color: #888888; font-weight: bold } /* Keyword.Type */
.highlight .m { color: #0000DD; font-weight: bold } /* Literal.Number */
.highlight .s { color: #dd2200; background-color: #fff0f0 } /* Literal.String */
.highlight .na { color: #336699 } /* Name.Attribute */
.highlight .nb { color: #003388 } /* Name.Builtin */
.highlight .nc { color: #bb0066; font-weight: bold } /* Name.Class */
.highlight .no { color: #003366; font-weight: bold } /* Name.Constant */
.highlight .nd { color: #555555 } /* Name.Decorator */
.highlight .ne { color: #bb0066; font-weight: bold } /* Name.Exception */
.highlight .nf { color: #0066bb; font-weight: bold } /* Name.Function */
.highlight .nl { color: #336699; font-style: italic } /* Name.Label */
.highlight .nn { color: #bb0066; font-weight: bold } /* Name.Namespace */
.highlight .py { color: #336699; font-weight: bold } /* Name.Property */
.highlight .nt { color: #bb0066; font-weight: bold } /* Name.Tag */
.highlight .nv { color: #336699 } /* Name.Variable */
.highlight .ow { color: #008800 } /* Operator.Word */
.highlight .w { color: #bbbbbb } /* Text.Whitespace */
.highlight .mb { color: #0000DD; font-weight: bold } /* Literal.Number.Bin */
.highlight .mf { color: #0000DD; font-weight: bold } /* Literal.Number.Float */
.highlight .mh { color: #0000DD; font-weight: bold } /* Literal.Number.Hex */
.highlight .mi { color: #0000DD; font-weight: bold } /* Literal.Number.Integer */
.highlight .mo { color: #0000DD; font-weight: bold } /* Literal.Number.Oct */
.highlight .sa { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Affix */
.highlight .sb { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Backtick */
.highlight .sc { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Char */
.highlight .dl { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Delimiter */
.highlight .sd { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Doc */
.highlight .s2 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Double */
.highlight .se { color: #0044dd; background-color: #fff0f0 } /* Literal.String.Escape */
.highlight .sh { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Heredoc */
.highlight .si { color: #3333bb; background-color: #fff0f0 } /* Literal.String.Interpol */
.highlight .sx { color: #22bb22; background-color: #f0fff0 } /* Literal.String.Other */
.highlight .sr { color: #008800; background-color: #fff0ff } /* Literal.String.Regex */
.highlight .s1 { color: #dd2200; background-color: #fff0f0 } /* Literal.String.Single */
.highlight .ss { color: #aa6600; background-color: #fff0f0 } /* Literal.String.Symbol */
.highlight .bp { color: #003388 } /* Name.Builtin.Pseudo */
.highlight .fm { color: #0066bb; font-weight: bold } /* Name.Function.Magic */
.highlight .vc { color: #336699 } /* Name.Variable.Class */
.highlight .vg { color: #dd7700 } /* Name.Variable.Global */
.highlight .vi { color: #3333bb } /* Name.Variable.Instance */
.highlight .vm { color: #336699 } /* Name.Variable.Magic */
.highlight .il { color: #0000DD; font-weight: bold } /* Literal.Number.Integer.Long */
# http://rosettacode.org/wiki/N-queens_problem
# port of the Arc solution at http://arclanguage.org/item?id=19743
#
#include <stdio.h>
#include <stdlib.h>
#include <ncurses.h>
#include <string.h>
#include <strophe/strophe.h>

#include "log.h"

// refernce to log
extern FILE *logp;

// area for log message in profanity
static const char *prof = "prof";

// chat windows
static WINDOW *incoming_border;
static WINDOW *outgoing_border;
static WINDOW *incoming;
static WINDOW *outgoing;
static int incoming_ypos = 0;
static int inc_scroll_max = 0;

// message handlers
int in_message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, 
    void * const userdata);

int out_message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, 
    void * const userdata);

// connection handler
void 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);

// curses functions
void init(void);
void print_title(void);
void close(void);

WINDOW *create_win(int, int, int, int, int);
void create_conversation(void);

int main(void)
{   
    int ypos = 2;
    int xpos = 2;
    char user[50];
    char passwd[50];

    xmpp_ctx_t *ctx;
    xmpp_conn_t *conn;
    xmpp_log_t *log;

    logp = fopen("profanity.log", "a");
    logmsg(prof, "Starting Profanity...");

    init();
    print_title();
    ypos += 2;
    mvprintw(ypos, xpos, "Enter jabber ID (username@host) : ");
    echo();
    getstr(user);

    ypos += 2;
    mvprintw(ypos, xpos, "Enter passwd : ");
    noecho();
    getstr(passwd);
    echo();
    
    char loginmsg[100];
    sprintf(loginmsg, "User <%s> logged in", user);
    logmsg(prof, loginmsg);
    //fprintf(logp, "Log in, user = %s\n", user);
    
    xmpp_initialize();
    
    log = xmpp_get_file_logger(); 
    ctx = xmpp_ctx_new(NULL, log);
    conn = xmpp_conn_new(ctx);

    xmpp_conn_set_jid(conn, user);
    xmpp_conn_set_pass(conn, passwd);

    xmpp_connect_client(conn, NULL, 0, conn_handler, ctx);
    
    clear();
    print_title();
    refresh();
    move(3, 0);

    create_conversation();

    xmpp_run(ctx);

    xmpp_conn_release(conn);
    xmpp_ctx_free(ctx);

    xmpp_shutdown();

    close();

    fclose(logp);

    return 0;
}

int in_message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, 
    void * const userdata)
{
    char *intext;

    if(!xmpp_stanza_get_child_by_name(stanza, "body")) 
        return 1;
    if(!strcmp(xmpp_stanza_get_attribute(stanza, "type"), "error")) 
        return 1;

    intext = xmpp_stanza_get_text(xmpp_stanza_get_child_by_name(stanza, "body"));

    char in_line[100];    
    sprintf(in_line, "%s: %s\n", xmpp_stanza_get_attribute(stanza, "from"), intext);

    if (incoming_ypos == inc_scroll_max-1) {
        scroll(incoming);
        mvwaddstr(incoming, incoming_ypos-1, 0, in_line);
    } else {
        mvwaddstr(incoming, incoming_ypos, 0, in_line);
        incoming_ypos++;
    }

    wrefresh(incoming);

    return 1;
}

int out_message_handler(xmpp_conn_t * const conn, xmpp_stanza_t * const stanza, 
    void * const userdata)
{
    char replytxt[100];;

    echo();
    wgetstr(outgoing, replytxt);
        
    wrefresh(outgoing);
    refresh();

    xmpp_stanza_t *reply, *body, *text;
    xmpp_ctx_t *ctx = (xmpp_ctx_t*)userdata;

    reply = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(reply, "message");
    xmpp_stanza_set_type(reply, 
        xmpp_stanza_get_type(stanza)?xmpp_stanza_get_type(stanza):"chat");
    xmpp_stanza_set_attribute(reply, "to", xmpp_stanza_get_attribute(stanza, "from"));

    body = xmpp_stanza_new(ctx);
    xmpp_stanza_set_name(body, "body");

    text = xmpp_stanza_new(ctx);
    xmpp_stanza_set_text(text, replytxt);
    xmpp_stanza_add_child(body, text);
    xmpp_stanza_add_child(reply, body);

    xmpp_send(conn, reply);
    xmpp_stanza_release(reply);

    return 1;
}

void 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) {
        xmpp_stanza_t* pres;
        fprintf(logp, "DEBUG: connected\n");
        xmpp_handler_add(conn,in_message_handler, NULL, "message", NULL, ctx);
        xmpp_handler_add(conn,out_message_handler, NULL, "message", NULL, ctx);

        pres = xmpp_stanza_new(ctx);
        xmpp_stanza_set_name(pres, "presence");
        xmpp_send(conn, pres);
        xmpp_stanza_release(pres);
    }
    else {
        fprintf(logp, "DEBUG: disconnected\n");
        xmpp_stop(ctx);
    }
}

void init(void)
{
    initscr();
    cbreak();
    keypad(stdscr, TRUE);
    start_color();

    init_color(COLOR_WHITE, 1000, 1000, 1000);
    init_pair(1, COLOR_WHITE, COLOR_BLACK);
    init_pair(2, COLOR_GREEN, COLOR_BLACK);

    init_color(COLOR_BLUE, 0, 0, 250);
    init_pair(3, COLOR_WHITE, COLOR_BLUE);

    attron(A_BOLD);
    attron(COLOR_PAIR(1));
}

WINDOW *create_win(int height, int width, int starty, int startx, int border)
{   
    WINDOW *local_win;

    local_win = newwin(height, width, starty, startx);
    if (border)    
        box(local_win, 0 , 0);     
    wrefresh(local_win);

    return local_win;
}

void create_conversation()
{
    int rows, cols;
    char *title = "PROFANITY";

    getmaxyx(stdscr, rows, cols);
    
    curs_set(0);
    attron(COLOR_PAIR(3));
    mvprintw(1, (cols - strlen(title))/2, title);
    attroff(COLOR_PAIR(3));

    int in_height, in_width, in_y, in_x;
    int out_height, out_width, out_y, out_x;

    out_height = 5;
    out_width = cols;
    out_y = rows - 5;
    out_x = 0;

    in_height = (rows - 3) - (out_height);
    in_width = cols;
    in_y = 3;
    in_x = 0;
    
    incoming_border = create_win(in_height, in_width, in_y, in_x, 1);
    outgoing_border = create_win(out_height, out_width, out_y, out_x, 1);
    inc_scroll_max = in_height-2;
    incoming = create_win(in_height-2, in_width-2, in_y+1, in_x+1, 0);
    scrollok(incoming, TRUE);
    outgoing = create_win(out_height-2, out_width-2, out_y+1, out_x+1, 0);
    scrollok(outgoing, TRUE);
}

void print_title(void)
{
    int rows, cols;
    char *title = "PROFANITY";

    getmaxyx(stdscr, rows, cols);
    
    attron(COLOR_PAIR(3));
    mvprintw(1, (cols - strlen(title))/2, title);
    attroff(COLOR_PAIR(3));
}

void close(void)
{
    int rows, cols;
    char *exit_msg = "< HIT ANY KEY TO EXIT >";

    getmaxyx(stdscr, rows, cols);
    
    attron(A_BLINK);
    curs_set(0);
    mvprintw(rows-10, (cols - strlen(exit_msg))/2, exit_msg);
    
    refresh();
    getch();
    endwin();
}