blob: 42926e3dee55f7d5d646de89660fa4668baa106b [file] [log] [blame]
adamdunkelsa2f3c422004-09-12 20:24:53 +00001/*
2 * Copyright (c) 2004, Adam Dunkels.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. Neither the name of the Institute nor the names of its contributors
14 * may be used to endorse or promote products derived from this software
15 * without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
18 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
21 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27 * SUCH DAMAGE.
28 *
29 * This file is part of the Contiki operating system.
30 *
31 * Author: Adam Dunkels <adam@sics.se>
32 *
oliverschmidtb86b0652005-04-24 13:37:42 +000033 * $Id: irc.c,v 1.7 2005/04/24 13:37:42 oliverschmidt Exp $
adamdunkelsa2f3c422004-09-12 20:24:53 +000034 */
adamdunkels999e3722004-09-03 08:23:56 +000035
adamdunkels44cce8c2004-09-09 21:05:24 +000036#include "irc-conf.h"
adamdunkels5a2df1c2004-09-01 19:11:42 +000037#include "contiki.h"
adamdunkels999e3722004-09-03 08:23:56 +000038#include "ircc.h"
39
adamdunkels5a2df1c2004-09-01 19:11:42 +000040#include "ctk.h"
41#include "ctk-textedit.h"
42
adamdunkels28c6f902004-09-05 07:13:30 +000043#include "petsciiconv.h"
44
adamdunkels5a2df1c2004-09-01 19:11:42 +000045#include <string.h>
46
adamdunkels44cce8c2004-09-09 21:05:24 +000047#define LOG_WIDTH IRC_CONF_WIDTH
48#define LOG_HEIGHT IRC_CONF_HEIGHT
49/*
adamdunkels28c6f902004-09-05 07:13:30 +000050#define LOG_WIDTH 78
adamdunkels999e3722004-09-03 08:23:56 +000051#define LOG_HEIGHT 21
adamdunkels44cce8c2004-09-09 21:05:24 +000052*/
adamdunkels5a2df1c2004-09-01 19:11:42 +000053EK_EVENTHANDLER(eventhandler, ev, data);
54EK_PROCESS(p, "IRC client", EK_PRIO_NORMAL,
55 eventhandler, NULL, NULL);
56static ek_id_t id = EK_ID_NONE;
57
58static struct ctk_window window;
59static char log[LOG_WIDTH * LOG_HEIGHT];
adamdunkels28c6f902004-09-05 07:13:30 +000060static char line[LOG_WIDTH*2];
adamdunkels5a2df1c2004-09-01 19:11:42 +000061static struct ctk_label loglabel =
62 {CTK_LABEL(0, 0, LOG_WIDTH, LOG_HEIGHT, log)};
adamdunkels28c6f902004-09-05 07:13:30 +000063static struct ctk_textentry lineedit =
64 {CTK_TEXTENTRY(0, LOG_HEIGHT, LOG_WIDTH - 2, 1, line, sizeof(line) - 1)};
adamdunkels5a2df1c2004-09-01 19:11:42 +000065
66static struct ctk_window setupwindow;
67#define SETUPWINDOW_WIDTH 18
68#define SETUPWINDOW_HEIGHT 9
69#define MAX_SERVERLEN 32
70#define MAX_NICKLEN 16
71static u16_t serveraddr[2];
adamdunkels28c6f902004-09-05 07:13:30 +000072static char server[MAX_SERVERLEN + 1];
73static char nick[MAX_NICKLEN + 1];
adamdunkels5a2df1c2004-09-01 19:11:42 +000074static struct ctk_label serverlabel =
75 {CTK_LABEL(1, 1, 11, 1, "IRC server: ")};
76static struct ctk_textentry serverentry =
adamdunkels28c6f902004-09-05 07:13:30 +000077 {CTK_TEXTENTRY(0, 2, 16, 1, server, MAX_SERVERLEN)};
adamdunkels5a2df1c2004-09-01 19:11:42 +000078
79static struct ctk_label nicklabel =
80 {CTK_LABEL(1, 4, 13, 1, "IRC nickname: ")};
81static struct ctk_textentry nickentry =
adamdunkels28c6f902004-09-05 07:13:30 +000082 {CTK_TEXTENTRY(0, 5, 16, 1, nick, MAX_NICKLEN)};
adamdunkels5a2df1c2004-09-01 19:11:42 +000083
adamdunkels5a2df1c2004-09-01 19:11:42 +000084static struct ctk_button connectbutton =
adamdunkels999e3722004-09-03 08:23:56 +000085 {CTK_BUTTON(0, 7, 7, "Connect")};
86static struct ctk_button quitbutton =
87 {CTK_BUTTON(12, 7, 4, "Quit")};
adamdunkels5a2df1c2004-09-01 19:11:42 +000088
89/*static char nick[] = "asdf";
90 static char server[] = "efnet.demon.co.uk";*/
91
92static struct ircc_state s;
93
94/*---------------------------------------------------------------------------*/
95LOADER_INIT_FUNC(irc_init, arg)
96{
97 arg_free(arg);
98
99 if(id == EK_ID_NONE) {
100 id = ek_start(&p);
101 }
102}
103/*---------------------------------------------------------------------------*/
104static void
105quit(void)
106{
adamdunkels999e3722004-09-03 08:23:56 +0000107 ctk_window_close(&window);
108 ctk_window_close(&setupwindow);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000109 ek_exit();
110 id = EK_ID_NONE;
111 LOADER_UNLOAD();
112}
113/*---------------------------------------------------------------------------*/
114void
115ircc_text_output(struct ircc_state *s, char *text1, char *text2)
116{
117 char *ptr;
adamdunkels28c6f902004-09-05 07:13:30 +0000118 int len;
adamdunkels999e3722004-09-03 08:23:56 +0000119
adamdunkels5a2df1c2004-09-01 19:11:42 +0000120 if(text1 == NULL) {
121 text1 = "";
122 }
123
124 if(text2 == NULL) {
125 text2 = "";
126 }
127
128 /* Scroll previous entries upwards */
129 memcpy(log, &log[LOG_WIDTH], LOG_WIDTH * (LOG_HEIGHT - 1));
130
131 ptr = &log[LOG_WIDTH * (LOG_HEIGHT - 1)];
132 len = strlen(text1);
133
134 memset(ptr, 0, LOG_WIDTH);
135 strncpy(ptr, text1, LOG_WIDTH);
adamdunkels28c6f902004-09-05 07:13:30 +0000136 if(len < LOG_WIDTH) {
137 ptr += len;
138 *ptr = ':';
139 ++len;
140 if(LOG_WIDTH - len > 0) {
141 strncpy(ptr + 1, text2, LOG_WIDTH - len);
142 }
143 } else {
144 len = 0;
adamdunkels5a2df1c2004-09-01 19:11:42 +0000145 }
146
adamdunkels28c6f902004-09-05 07:13:30 +0000147 if(strlen(text2) > LOG_WIDTH - len) {
adamdunkels999e3722004-09-03 08:23:56 +0000148 memcpy(log, &log[LOG_WIDTH], LOG_WIDTH * (LOG_HEIGHT - 1));
149 strncpy(&log[LOG_WIDTH * (LOG_HEIGHT - 1)],
adamdunkels28c6f902004-09-05 07:13:30 +0000150 text2 + LOG_WIDTH - len, LOG_WIDTH);
adamdunkels999e3722004-09-03 08:23:56 +0000151 }
adamdunkels5a2df1c2004-09-01 19:11:42 +0000152 CTK_WIDGET_REDRAW(&loglabel);
153
154}
155/*---------------------------------------------------------------------------*/
156static void
157parse_line(void)
158{
159 int i;
160 for(i = 0; i < strlen(line); ++i) {
161 line[i] &= 0x7f;
162 }
163
164
165 if(line[0] == '/') {
adamdunkels999e3722004-09-03 08:23:56 +0000166 if(strncmp(&line[1], "join", 4) == 0) {
adamdunkels5a2df1c2004-09-01 19:11:42 +0000167 ircc_join(&s, &line[6]);
168 ircc_text_output(&s, "Join", &line[6]);
adamdunkels999e3722004-09-03 08:23:56 +0000169 } else if(strncmp(&line[1], "list", 4) == 0) {
adamdunkels5a2df1c2004-09-01 19:11:42 +0000170 ircc_list(&s);
171 ircc_text_output(&s, "Channel list", "");
adamdunkels999e3722004-09-03 08:23:56 +0000172 } else if(strncmp(&line[1], "part", 4) == 0) {
adamdunkels5a2df1c2004-09-01 19:11:42 +0000173 ircc_part(&s);
174 ircc_text_output(&s, "Leaving channel", "");
adamdunkels999e3722004-09-03 08:23:56 +0000175 } else if(strncmp(&line[1], "quit", 4) == 0) {
176 ircc_quit(&s);
adamdunkels44cce8c2004-09-09 21:05:24 +0000177 } else if(strncmp(&line[1], "me", 2) == 0) {
178 petsciiconv_toascii(&line[4], strlen(&line[4]));
179 ircc_actionmsg(&s, &line[4]);
180 ircc_text_output(&s, "*", &line[4]);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000181 } else {
182 ircc_text_output(&s, &line[1], "Not implemented");
183 ircc_sent(&s);
184 }
185 } else {
adamdunkels28c6f902004-09-05 07:13:30 +0000186 petsciiconv_toascii(line, sizeof(line) - 1);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000187 ircc_msg(&s, &line[0]);
188 ircc_text_output(&s, nick, line);
189 }
190
191}
192/*---------------------------------------------------------------------------*/
193void
194ircc_sent(struct ircc_state *s)
195{
adamdunkels28c6f902004-09-05 07:13:30 +0000196 /* ctk_textedit_init(&lineedit);*/
197 CTK_TEXTENTRY_CLEAR(&lineedit);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000198 CTK_WIDGET_REDRAW(&lineedit);
adamdunkels44cce8c2004-09-09 21:05:24 +0000199 CTK_WIDGET_FOCUS(&window, &lineedit);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000200}
201/*---------------------------------------------------------------------------*/
202EK_EVENTHANDLER(eventhandler, ev, data)
203{
204 ctk_arch_key_t c;
205 u16_t *ipaddr;
206
207 if(ev == EK_EVENT_INIT) {
adamdunkels28c6f902004-09-05 07:13:30 +0000208 /* ctk_textedit_init(&lineedit);*/
209 CTK_TEXTENTRY_CLEAR(&lineedit);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000210 memset(log, 0, sizeof(log));
211 ctk_window_new(&window, LOG_WIDTH, LOG_HEIGHT + 1, "IRC");
212 CTK_WIDGET_ADD(&window, &loglabel);
adamdunkels28c6f902004-09-05 07:13:30 +0000213 /* ctk_textedit_add(&window, &lineedit); */
214 CTK_WIDGET_ADD(&window, &lineedit);
215 CTK_WIDGET_FOCUS(&window, &lineedit);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000216
217 ctk_window_new(&setupwindow, SETUPWINDOW_WIDTH, SETUPWINDOW_HEIGHT,
218 "IRC setup");
219
220 CTK_WIDGET_ADD(&setupwindow, &serverlabel);
221 CTK_WIDGET_ADD(&setupwindow, &serverentry);
222 CTK_WIDGET_ADD(&setupwindow, &nicklabel);
223 CTK_WIDGET_ADD(&setupwindow, &nickentry);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000224 CTK_WIDGET_ADD(&setupwindow, &connectbutton);
adamdunkels999e3722004-09-03 08:23:56 +0000225 CTK_WIDGET_ADD(&setupwindow, &quitbutton);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000226
oliverschmidtb86b0652005-04-24 13:37:42 +0000227 CTK_WIDGET_FOCUS(&setupwindow, &serverentry);
228
adamdunkels5a2df1c2004-09-01 19:11:42 +0000229 ctk_window_open(&setupwindow);
230
adamdunkels28c6f902004-09-05 07:13:30 +0000231 } else if(ev == EK_EVENT_REQUEST_EXIT) {
232 quit();
233 } else if(ev == ctk_signal_window_close) {
adamdunkels5a2df1c2004-09-01 19:11:42 +0000234 quit();
235 } else if(ev == tcpip_event) {
236 ircc_appcall(data);
237 } else if(ev == ctk_signal_widget_activate) {
238 if(data == (ek_data_t)&lineedit) {
239 parse_line();
240 } else if(data == (ek_data_t)&quitbutton) {
adamdunkels5a2df1c2004-09-01 19:11:42 +0000241 quit();
242 } else if(data == (ek_data_t)&connectbutton) {
243 ctk_window_close(&setupwindow);
244 ctk_window_open(&window);
245 ipaddr = serveraddr;
adamdunkels999e3722004-09-03 08:23:56 +0000246 if(uiplib_ipaddrconv(server, (u8_t *)serveraddr) == 0) {
adamdunkels5a2df1c2004-09-01 19:11:42 +0000247 ipaddr = resolv_lookup(server);
248 if(ipaddr == NULL) {
249 resolv_query(server);
250 } else {
251 uip_ipaddr_copy(serveraddr, ipaddr);
252 }
253 }
254 if(ipaddr != NULL) {
255
256 ircc_connect(&s, server, serveraddr, nick);
257 }
258 }
259 } else if(ev == resolv_event_found) {
260
261 ipaddr = resolv_lookup(server);
262 if(ipaddr == NULL) {
263 ircc_text_output(&s, server, "hostname not found");
264 } else {
265 uip_ipaddr_copy(serveraddr, ipaddr);
266 ircc_connect(&s, server, serveraddr, nick);
267 }
268
269 } else if(ev == ctk_signal_keypress) {
270 c = (ctk_arch_key_t)data;
271 if(c == CH_ENTER) {
272 parse_line();
273 } else {
adamdunkels28c6f902004-09-05 07:13:30 +0000274 /* ctk_textedit_eventhandler(&lineedit, ev, data);*/
275 CTK_WIDGET_FOCUS(&window, &lineedit);
adamdunkels5a2df1c2004-09-01 19:11:42 +0000276 }
277 }
278}
279/*---------------------------------------------------------------------------*/
280void
281ircc_closed(struct ircc_state *s)
282{
283 ircc_text_output(s, server, "connection closed");
284}
285/*---------------------------------------------------------------------------*/
286void
287ircc_connected(struct ircc_state *s)
288{
289 ircc_text_output(s, server, "connected");
290}
291/*---------------------------------------------------------------------------*/