/* FujiNetChat, an IRC client. Based on NetCat and the old FujiChat. */ #define SELF "FujiNetChat" #define VERSION "0.0" #define BANNER SELF " v" VERSION " (B. Watson)\n" #include #include #include #include #include #include // for cgetc() only #include "nio.h" #include "irc.h" #include "screen.h" #include "edbox.h" #include "config.h" unsigned char err; // error code of last operation. unsigned char trip = 0; // if trip == 1, fujinet is asking us for attention. char old_enabled = 0; // were interrupts enabled for old vector void *old_vprced; // old PROCEED vector, restored on exit. unsigned short rxbuflen; // RX buffer length unsigned int txbuflen; // TX buffer length char hz; /* 50 for PAL, 60 for NSTC */ /* TODO: user modes (default +iw), fg/bg color... */ extern void ih(); // defined in intr.s void txbuf_init(void) { txbuflen = tx_buf[0] = 0; } void txbuf_append_str(const char *str) { while(*str) { tx_buf[txbuflen++] = *str++; } } void txbuf_append_str2(const char *s1, const char *s2) { txbuf_append_str(s1); txbuf_append_str(s2); } void txbuf_append_str3(const char *s1, const char *s2, const char *s3) { txbuf_append_str(s1); txbuf_append_str(s2); txbuf_append_str(s3); } void txbuf_set_str(const char *str) { txbuf_init(); txbuf_append_str(str); } void txbuf_set_str2(const char *s1, const char *s2) { txbuf_set_str(s1); txbuf_append_str(s2); } void txbuf_set_str3(const char *s1, const char *s2, const char *s3) { txbuf_set_str2(s1, s2); txbuf_append_str(s3); } void txbuf_send(void) { /* don't send empty buffer */ if(!txbuflen) return; /* always terminate with EOL */ if(tx_buf[txbuflen - 1] != '\n') tx_buf[txbuflen++] = '\n'; nwrite(conf->url, tx_buf, txbuflen); txbuf_init(); } void txbuf_send_str(const char *str) { txbuf_init(); txbuf_append_str(str); txbuf_send(); } int fn_connect(void) { scr_print(SCR_SERVER, "Connecting to: "); scr_print(SCR_SERVER, conf->url); scr_print(SCR_SERVER, "\n"); err = nopen(conf->url, FNET_TRANSLATION); if(err != SUCCESS) { scr_print(SCR_SERVER, "Connection failed: "); print_errnum(); return 0; } // Open successful, set up interrupt old_vprced = OS.vprced; // save the old interrupt vector old_enabled = PIA.pactl & 1; // keep track of old interrupt state PIA.pactl &= (~1); // Turn off interrupts before changing vector OS.vprced = ih; // Set PROCEED interrupt vector to our interrupt handler. PIA.pactl |= 1; // Indicate to PIA we are ready for PROCEED interrupt. return 1; } void fn_disconnect(void) { // Restore old PROCEED interrupt. PIA.pactl &= ~1; // disable interrupts OS.vprced=old_vprced; PIA.pactl |= old_enabled; } void init_channels(void) { char i; for(i = 0; i < MAX_SCREENS - 2; i++) { if(conf->channels[i][0]) { scr_status[i + 2] = SCR_INACTIVE; strcpy(scr_names[i + 2], conf->channels[i]); } } } void main(void) { bell_type = conf->alert_type; /* TODO: have bell.s read staight from the struct */ OS.shflok = 0; // turn off shift-lock. OS.soundr = 0; // Turn off SIO beeping sound OS.color2 = conf->colors[0]; OS.color1 = conf->colors[1]; OS.noclik = conf->disable_keyclick; hz = (GTIA_READ.pal & 0x0e) ? 60 : 50; edbox_clear(); scr_init(); init_channels(); while(1) { edbox_callback = cmd_execute; if(fn_connect()) { irc_register(); irc_loop(); fn_disconnect(); } } }