diff options
| -rw-r--r-- | README.md | 64 | ||||
| -rw-r--r-- | hexsparkles.c | 62 | ||||
| -rw-r--r-- | sparkles.c | 62 | 
3 files changed, 173 insertions, 15 deletions
| @@ -135,7 +135,7 @@ CR   | Switch to random capitalization  Repeats Text as many times as Times specifies and says it  ### space2newline -`/spark space2newline` +`/spark space2newline Text`  makes @@ -147,6 +147,15 @@ like  this +### spaces2newline +`/spark spaces2newline Count Text` + +Specifies amount of "words" to have per line + +### spaceysay +`/spark spaceysay Text` +Inserts spaces between every two characters +  ### rot13  `/spark rot13 Text` @@ -364,10 +373,12 @@ Set a specific config option. Yes/no and on/off are accepted for boolean options  Option                        | Effect  ----------------------------- | ------  General TextEditor            | Path to a text editor to use +General QuietOnEvents         | Doesn't say anything when doing /spark onevent  Automatic ForceUTF8           | Force UTF-8 in all channels  Automatic CharCounter         | Displays a character counter if on  Automatic DisableNetworkSayer | Disable showing the network name upon joining a channel  Automatic DisableHighlights   | Disables highlights if on +Automatic PMAlerts            | Alert if PM'd with the window focused (see also PMAlertsEvenWithoutFocus and PMAlertsEvenWithSameNetwork)  Pesterchum ChannelCommand     | Command to use when speaking on Pesterchum channels  Pesterchum Color              | Color to use when speaking on Pesterchum channels (R,G,B) @@ -511,6 +522,53 @@ Copies the current topic to the input box with colors and effects included.  Runs a program like /exec but asynchronously (only supported on Windows currently)  ======= +### on event +`/spark onevent list` + +`/spark onevent delete all/number` + +`/spark onevent enable all/number` + +`/spark onevent disable all/number` + +List, delete, enable or disable onevent numbers + +`/spark onevent renumber` + +Reorder the list to get rid of any gaps. + +`/spark onevent set Flags EventName Condition Condition Condition Response` + +Add an OnEvent trigger, which will run Response as a command when a text event happens with specific conditions. + +Conditions are set up like "1=text" where the number is the parameter number in the text events list. +Use two =s for a case-sensitive compare, or != or !== for a condition that's true if it's not equal. +Use a * at the start and/or end of the thing ot compare to if you want to put a wildcard there. + +0 is a special parameter: + +0x   | Effect +---- | ------ +0c   | Channel or tab name +0n   | Nick +0N   | Network +0s   | Server +0w   | Window status: active, normal or hidden + +Flag | Effect +---- | ------ +1-29 | Must be the first thing in the flags; selects a slot +h    | Use high priority when registering the hook +s    | Save trigger in Sparkles config when that's saved +t    | Trigger is temporary and disables  +d    | Trigger starts out disabled + +If you don't have any flags you can use "." in place of any flags. +The response can use $1, $2, $3 etc to refer to the text event parameters, or $n or $c for your nick or the channel name. $$ comes out as a $. + +"DeleteEvent" is accepted as a response and it will delete the event. + +=======  ### chancolorset  `/spark chancolorset N` @@ -536,3 +594,7 @@ Saves preferences to a .ini file  `/spark randnum Limit`  Generates a random number + +### echofocused +`/spark echofocused Text` +Prints text to the currently focused tab diff --git a/hexsparkles.c b/hexsparkles.c index 902dfd4..eec168a 100644 --- a/hexsparkles.c +++ b/hexsparkles.c @@ -185,11 +185,16 @@ int memcasecmp(const char *Text1, const char *Text2, int Length) {  }  static int isgraph2(char k) { // unicode version -  if(!isgraph(k)) return 0;    unsigned char k2 = (unsigned char)k; +  if(!isgraph(k) && k2 < 0xc0) return 0;    return k2<0x80||k2>0xbf;  } +static int iscontinuationbyte(char k) { +  unsigned char k2 = (unsigned char)k; +  return k2>=0x80&&k2<=0xbf; +} +  static char *ReadTextFile(const char *Name) {    FILE *File = fopen(Name,"rb");    if(!File) return NULL; @@ -271,10 +276,10 @@ static int OETextMatch(char *Inputs[], const char *MatchTo) {      case 1: // *@        End = strrchr(Input, 0);        End -= strlen(Match); -      Decision = memcasecmp(End, Match, strlen(Match)); +      Decision = !memcasecmp(End, Match, strlen(Match));        break;      case 2: // @* -      Decision = memcasecmp(Input, Match, strlen(Match)); +      Decision = !memcasecmp(Input, Match, strlen(Match));        break;      case 3: // *@*        Decision = strstr(Input, Match) != NULL; @@ -384,9 +389,15 @@ static int on_event_cb(char *word[], void *userdata) {    hexchat_free(ph, Word3);    hexchat_free(ph, Word4); +  if(!strcasecmp(Buffer, "DeleteEvent")) +    return HEXCHAT_EAT_ALL; +    hexchat_command(ph, Buffer); -  if(Info->Flags & OEF_TEMPORARY) +  if(Info->Flags & OEF_TEMPORARY) { +    QuietOnEvents++;      hexchat_commandf(ph, "spark onevent delete %i", Info->Slot); +    QuietOnEvents--; +  }    return HEXCHAT_EAT_NONE;  } @@ -808,6 +819,12 @@ static int AttributeLoop(char *Out, char *In, char *Loop) {    int LoopTimes = 0;    for(;i<EndI;) { +    if(iscontinuationbyte(In[i])) { +      while(iscontinuationbyte(In[i])) { +        Out[o++] = In[i++]; +      } +      continue; +    }      switch(Loop[s++]) {        case 'c':          Out[o++]=0x03; @@ -2142,6 +2159,12 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {           fprintf(Output, "%s=%i\n", ConfigOptions[i].Item, *(int*)ConfigOptions[i].Data);         }       } +     fprintf(Output, "\n[OnEventList]\n"); +     for(i=0;i<ONEVENTS_SIZE;i++) +       if(OnEventInfos[i] && OnEventInfos[i]->Flags & OEF_SAVE) { +         ListOnEvent(Buffer, OnEventInfos[i]); +         fprintf(Output, "%i=%s\n", i, Buffer); +       }       fclose(Output);       hexchat_print(ph, "Saved Sparkles preferences\n");     } @@ -2938,6 +2961,7 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {               OnEventInfos[i] = OnEventInfos[j];               OnEventInfos[j] = NULL;               OnEventInfos[i]->Slot = i; +             break;             }         }         hexchat_print(ph, "Renumbered the OnEvent list"); @@ -2967,7 +2991,7 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {           if(OnEventInfos[j]) {             OnEventInfos[j]->Flags &= ~OEF_ENABLED;             if(!QuietOnEvents) -             hexchat_printf(ph, "Disabling OnEvent item %i", i); +             hexchat_printf(ph, "Disabling OnEvent item %i", j);           }         }       } else if(!strcasecmp(word[3], "enable")) { @@ -2976,13 +3000,16 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {           if(OnEventInfos[j]) {             OnEventInfos[j]->Flags |= OEF_ENABLED;             if(!QuietOnEvents) -             hexchat_printf(ph, "Enabling OnEvent item %i", i); +             hexchat_printf(ph, "Enabling OnEvent item %i", j);           }         }       } else if(!strcasecmp(word[3], "set")) {         j = -1; -       if(isdigit(word[4][0])) // user selected a specific slot +       if(isdigit(word[4][0])) { // user selected a specific slot           j = strtol(word[4], NULL, 10); +         if(j < 0 || j >= ONEVENTS_SIZE) +           return HEXCHAT_EAT_ALL; +       }         if(j == -1) {           for(j=0;j<ONEVENTS_SIZE;j++)             if(!OnEventInfos[j]) @@ -3328,6 +3355,21 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {         hexchat_list_free(ph, list);       }     } + +   if(!strcasecmp(word[2],"spaceysay")) { +     WasValid = 1; +     hexchat_commandf(ph, "spark atloop |*_ say %s", word_eol[3]); +   } + +   if(!strcasecmp(word[2],"echofocused")) { // echo to focused tab +     WasValid = 1; +     hexchat_context *Focused = hexchat_find_context(ph, NULL, NULL); +     hexchat_context *This = hexchat_get_context(ph); +     hexchat_set_context(ph, Focused); +     hexchat_print(ph, word_eol[3]); +     hexchat_set_context(ph, This); +   } +     if(!strcasecmp(word[2],"rchan")) { // with preserved context       WasValid = 1;       hexchat_command(ph, "spark contextstack push"); @@ -3630,6 +3672,12 @@ static int channelmessage_cb(char *word[], void *userdata) {  void INIConfigHandler(const char *Group, const char *Item, const char *Value) {  //  printf("[%s] %s = %s\n", Group, Item, Value); +  if(!strcasecmp(Group, "OnEventList")) { +    QuietOnEvents++; +    hexchat_commandf(ph, "spark onevent set %s", Value); +    QuietOnEvents--; +    return; +  }    int i, *Int;    char *String;    for(i=0;ConfigOptions[i].Group!=NULL;i++) @@ -185,11 +185,16 @@ int memcasecmp(const char *Text1, const char *Text2, int Length) {  }  static int isgraph2(char k) { // unicode version -  if(!isgraph(k)) return 0;    unsigned char k2 = (unsigned char)k; +  if(!isgraph(k) && k2 < 0xc0) return 0;    return k2<0x80||k2>0xbf;  } +static int iscontinuationbyte(char k) { +  unsigned char k2 = (unsigned char)k; +  return k2>=0x80&&k2<=0xbf; +} +  static char *ReadTextFile(const char *Name) {    FILE *File = fopen(Name,"rb");    if(!File) return NULL; @@ -271,10 +276,10 @@ static int OETextMatch(char *Inputs[], const char *MatchTo) {      case 1: // *@        End = strrchr(Input, 0);        End -= strlen(Match); -      Decision = memcasecmp(End, Match, strlen(Match)); +      Decision = !memcasecmp(End, Match, strlen(Match));        break;      case 2: // @* -      Decision = memcasecmp(Input, Match, strlen(Match)); +      Decision = !memcasecmp(Input, Match, strlen(Match));        break;      case 3: // *@*        Decision = strstr(Input, Match) != NULL; @@ -384,9 +389,15 @@ static int on_event_cb(char *word[], void *userdata) {    xchat_free(ph, Word3);    xchat_free(ph, Word4); +  if(!strcasecmp(Buffer, "DeleteEvent")) +    return XCHAT_EAT_ALL; +    xchat_command(ph, Buffer); -  if(Info->Flags & OEF_TEMPORARY) +  if(Info->Flags & OEF_TEMPORARY) { +    QuietOnEvents++;      xchat_commandf(ph, "spark onevent delete %i", Info->Slot); +    QuietOnEvents--; +  }    return XCHAT_EAT_NONE;  } @@ -808,6 +819,12 @@ static int AttributeLoop(char *Out, char *In, char *Loop) {    int LoopTimes = 0;    for(;i<EndI;) { +    if(iscontinuationbyte(In[i])) { +      while(iscontinuationbyte(In[i])) { +        Out[o++] = In[i++]; +      } +      continue; +    }      switch(Loop[s++]) {        case 'c':          Out[o++]=0x03; @@ -2142,6 +2159,12 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {           fprintf(Output, "%s=%i\n", ConfigOptions[i].Item, *(int*)ConfigOptions[i].Data);         }       } +     fprintf(Output, "\n[OnEventList]\n"); +     for(i=0;i<ONEVENTS_SIZE;i++) +       if(OnEventInfos[i] && OnEventInfos[i]->Flags & OEF_SAVE) { +         ListOnEvent(Buffer, OnEventInfos[i]); +         fprintf(Output, "%i=%s\n", i, Buffer); +       }       fclose(Output);       xchat_print(ph, "Saved Sparkles preferences\n");     } @@ -2938,6 +2961,7 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {               OnEventInfos[i] = OnEventInfos[j];               OnEventInfos[j] = NULL;               OnEventInfos[i]->Slot = i; +             break;             }         }         xchat_print(ph, "Renumbered the OnEvent list"); @@ -2967,7 +2991,7 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {           if(OnEventInfos[j]) {             OnEventInfos[j]->Flags &= ~OEF_ENABLED;             if(!QuietOnEvents) -             xchat_printf(ph, "Disabling OnEvent item %i", i); +             xchat_printf(ph, "Disabling OnEvent item %i", j);           }         }       } else if(!strcasecmp(word[3], "enable")) { @@ -2976,13 +3000,16 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {           if(OnEventInfos[j]) {             OnEventInfos[j]->Flags |= OEF_ENABLED;             if(!QuietOnEvents) -             xchat_printf(ph, "Enabling OnEvent item %i", i); +             xchat_printf(ph, "Enabling OnEvent item %i", j);           }         }       } else if(!strcasecmp(word[3], "set")) {         j = -1; -       if(isdigit(word[4][0])) // user selected a specific slot +       if(isdigit(word[4][0])) { // user selected a specific slot           j = strtol(word[4], NULL, 10); +         if(j < 0 || j >= ONEVENTS_SIZE) +           return XCHAT_EAT_ALL; +       }         if(j == -1) {           for(j=0;j<ONEVENTS_SIZE;j++)             if(!OnEventInfos[j]) @@ -3328,6 +3355,21 @@ static int Spark_cb(char *word[], char *word_eol[], void *userdata) {         xchat_list_free(ph, list);       }     } + +   if(!strcasecmp(word[2],"spaceysay")) { +     WasValid = 1; +     xchat_commandf(ph, "spark atloop |*_ say %s", word_eol[3]); +   } + +   if(!strcasecmp(word[2],"echofocused")) { // echo to focused tab +     WasValid = 1; +     xchat_context *Focused = xchat_find_context(ph, NULL, NULL); +     xchat_context *This = xchat_get_context(ph); +     xchat_set_context(ph, Focused); +     xchat_print(ph, word_eol[3]); +     xchat_set_context(ph, This); +   } +     if(!strcasecmp(word[2],"rchan")) { // with preserved context       WasValid = 1;       xchat_command(ph, "spark contextstack push"); @@ -3630,6 +3672,12 @@ static int channelmessage_cb(char *word[], void *userdata) {  void INIConfigHandler(const char *Group, const char *Item, const char *Value) {  //  printf("[%s] %s = %s\n", Group, Item, Value); +  if(!strcasecmp(Group, "OnEventList")) { +    QuietOnEvents++; +    xchat_commandf(ph, "spark onevent set %s", Value); +    QuietOnEvents--; +    return; +  }    int i, *Int;    char *String;    for(i=0;ConfigOptions[i].Group!=NULL;i++) | 
