/* 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" #include "keyclick.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 */ char reconnect_timeout = 1; /* 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_display(SCR_SERVER); scr_print_current("Connecting to: "); scr_print_current(conf->url); scr_eol_current(); err = nopen(conf->url, FNET_TRANSLATION); if(err != SUCCESS) { scr_print_current("Connection failed: "); print_errnum(); scr_eol_current(); bell(); 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. reconnect_timeout = 1; return 1; } void fn_disconnect(void) { nclose(conf->url); // 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 reconnect(void) { scr_display(SCR_SERVER); scr_print_current("Press a key"); /* IMO, 0xff is easier to understand than KEY_NONE, here */ OS.cdtmf3 = OS.ch = 0xff; if(reconnect_timeout) { OS.cdtmv3 = reconnect_timeout * hz; scr_print_current(" or wait "); itoa(reconnect_timeout, numbuf, 10); scr_print_current(numbuf); scr_print_current(" sec"); if(reconnect_timeout < 64) reconnect_timeout <<= 1; } scr_print_current(" to reconnect.\n"); while(OS.cdtmf3 == 0xff && OS.ch == 0xff) /* NOP */; if(OS.ch != 0xff) { keyclick(); OS.ch = 0xff; } } 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]; /* text BG, user-selected */ OS.color1 = (conf->colors[1] & 0x0f) | 0xc0; /* green (at user's brightness) */ OS.color0 = 0x06; /* grey for inactive */ OS.color3 = 0x46; /* red for highlight (not used yet) */ 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(); reconnect(); } }