From 201b9b3886cea07c29bf63c18a1b1d3b8952b6a7 Mon Sep 17 00:00:00 2001
From: Stephen Dranger <dranger@gmail.com>
Date: Sun, 13 Feb 2011 19:32:02 -0600
Subject: [PATCH] first feature freeze

---
 TODO           |  10 +++------
 convo.py       |  10 ++++++++-
 convo.pyc      | Bin 25610 -> 26081 bytes
 dataobjs.py    |  28 ++++++++++++++++++++++-
 dataobjs.pyc   | Bin 13108 -> 14106 bytes
 generic.py     |   9 ++++++++
 generic.pyc    | Bin 3575 -> 4285 bytes
 irc.py         |  18 ++++++++++++++-
 irc.pyc        | Bin 13203 -> 13654 bytes
 logs/chums.js  |   2 +-
 memos.py       |  23 ++++++++++++++-----
 memos.pyc      | Bin 31758 -> 32063 bytes
 menus.py       |  54 ++++++++++++++++++++++++++++++++++++++++++++
 menus.pyc      | Bin 23701 -> 25563 bytes
 mispeller.py   |  60 +++++++++++++++++++++++++++++++++++++++++++++++++
 mispeller.pyc  | Bin 0 -> 2929 bytes
 parsetools.py  |   6 +++++
 parsetools.pyc | Bin 10792 -> 10945 bytes
 pesterchum.js  |   2 +-
 pesterchum.py  |  11 ++++++++-
 20 files changed, 215 insertions(+), 18 deletions(-)
 create mode 100644 mispeller.py
 create mode 100644 mispeller.pyc

diff --git a/TODO b/TODO
index c68d534..9ea530e 100644
--- a/TODO
+++ b/TODO
@@ -1,8 +1,4 @@
 Features:
-* More complex quirks: spelling, by-sound
-* IRC message limit!!!
-* on ban, redirect to memo chooser
-* ? time option???
 * help menu -- about and forum
 * Tray doesn't disappear on windows after close
 -- release alpha
@@ -12,7 +8,9 @@ Features:
 * spell check?
 * help button on quirks menu?
 -- release beta
-* flashing??
+* hide offline chums
+* chum list groups
+* More complex quirks: by-sound
 * change profile only once we have confirmation from server
 * log viewer
 * pick your own icon
@@ -22,5 +20,3 @@ Features:
 * Spy mode
 * Animated
 * put code into separate files
-* hide offline chums
-* chum list groups
\ No newline at end of file
diff --git a/convo.py b/convo.py
index 7a7431f..9924f47 100644
--- a/convo.py
+++ b/convo.py
@@ -117,13 +117,16 @@ class PesterTabWindow(QtGui.QFrame):
             return True
         else:
             return False
-    
+    def activateChat(self):
+        if platform.system() == "Windows":
+            self.activateWindow()
     def notifyNewMessage(self, handle):
         i = self.tabIndices[handle]
         self.tabs.setTabTextColor(i, QtGui.QColor(self.mainwindow.theme["%s/tabs/newmsgcolor" % (self.type)]))
         convo = self.convos[handle]
         def func():
             convo.showChat()
+        self.activateChat()
         self.mainwindow.waitingMessages.addMessage(handle, func)
         # set system tray
     def clearNewMessage(self, handle):
@@ -480,6 +483,11 @@ class PesterConvo(QtGui.QFrame):
         if self.parent():
             self.parent().showChat(self.title())
         self.raiseChat()
+    def activateChat(self):
+        if self.parent():
+            self.parent().activateChat()
+        if platform.system() == "Windows":
+            self.activateWindow()
     def contextMenuEvent(self, event):
         if event.reason() == QtGui.QContextMenuEvent.Mouse:
             self.optionsMenu.popup(event.globalPos())
diff --git a/convo.pyc b/convo.pyc
index 965108344ff973ea6a500efdf8d33487bcca2ab1..1578fea33bf9d97985e8f426265fc4f17e3291d0 100644
GIT binary patch
delta 2684
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
Y7yaL~XgvezG;mh@!_GH+5ntZ_0Ir5y2LJ#7

delta 2313
zcmZvddr;I>6vyvb_$@Aopv%4hVHbR?G@xQ4f?^2hItrsdOcYdH*flpr)@4N<adZ_M
zQ&VS7Wxj%@86S-^rN3!<sr+H7DXBFoSsL0y9TO*Y%Km7Y&bcdy)gSjW-*fJ{?{n|H
zc@8$8fvB$^#zrsLS8*h&TG#iw5W*`&B?ylZ1G=3rc#XoBAiO5Afn5DXvtUta7SH$x
zbo(vRZxtJ;3!6~Ooe7#6Q9fXRj=GJcqNfr;rNNKq4L00sE{;-!&mer!_`rN9b`4i?
ztN>>W9<WTphZZOJG0CbLS8-jmtc!(Ah=n*EuD7m(Wf)-#K}g$ZYX;b)MJKfbY|}cD
zcLOwHAmt3~((+TM18l&p_BY^tOmk#FB9=Pb@j>cLUCKyhgz%&z9bU!Tjw<^Qa_Av0
z+0e%jWiS{NLq9`=LEo2E6#4pSp0ohK7g|U9MjbTai5!>0eVo<a8?s&x0nE&N1h1nb
zs|;GupOpe{;`XdecpHyr4T636KtEP#pzsTteRw%2A(H)Z<%or_13O2|0FyRy<UAl_
zd$vb8PL($NGy4kJ7e-m&BfLFIQ`*Suz?SE2S({0zTNqA;ks+7E1E}1!TF>Bq)HZx4
zuRz&O@^c(E`c7mMDcqD^1{vtdne${J+$Ixa#x%lyTtDVHI4vhN{Alj?K%Q%3?Ww0J
z!l@9{5sY%iImTCvi*kLHBuC+#ykVyQn_&od=DCzp6f+Ee&dct*7kbhz8S6$TD_*_u
zBx6zjs<o7QJ~JnjC%#vf^*DP{(#lEtB(f(TZM~ev?&gV4oZcjv)Ct}GWa%F$nev1i
z*6KuM>N6Fb|8}uRCl*CWzeD)agvTUucziO_g~!}u3=$rT$njW3&eQ0@y`zT+kF6(q
zsPH6Gbdt!abn@*PD1>%$+z`dOf_ADQmM~*dz+LCHueJ|vu&+^9B1{|y&04|4S9F6~
zs9Lo!?2Oe6K45h|BcHJe?-YL-!{@K=XPm-gCBGE3k_^TW+<yO(Rm+z90*f2e@m#-?
zv5OI4yv5kd;AnL>V-I#tvc|WQbQ;)}8PS4KlY>x<O_LAP1t@e+M!!peE!gNPA^VuC
z3SQH!Q}*lVrnF79Kr41kb%f_H2b06f3I1oW<Y^NecX^x#jNb^szJ!3cuD;P*SR3@!
zFIBs+X<9ZsmTBmr${kwQw0JN*+f4nNJLtlTt|FzH<Uy<~D>lhJJVd6GU!m|~4pB$B
z_-k1_e1LzIeKtzYP6o;cM9z~hTdy1Om>VBv9Avcg-1wuKb9xBee)68Bl<$7)_+-@*
zhV1PYtC5V!j9i8sD~Z)3#wLb^QOc0xKb^84qtyb1o1DN>^;n{8lEH!hYS+l?$91+y
zIFF0VXX)k0xAA6$OW{}J3MR~)*X`t;DkSH3*fz7RUnfsrPo|)!cpw%IFyg9NE8s3Z
zm=%PdFl%-SHdmC=6Z}m@72F~_pN{$E*;5owqPyD1vt7FQD<stp#<z^C;cUi&iK#mE
zvbMAeKp)OxTt0Vb)^(0K&$z~ryYd68PR0$!O~#LmNIWvvn0ue)Jw_LU(<QvaAy&Lt
zC;v*}bGEbkgYmmOFOIpVmCp;o#1BdOs0be?egk8AN%_nYwaE2iX`b3jc91)&4Z2@)
zCX!I=7;-nyv1&(ib^f4-B!m2J%8RDb4u(%omFM~{o2|IKIydzIOI~WPoRa<Yqc-Y6
zY_FaL3Z^gc(`|}37h%VOII!X#_tZGPgEdR)YZn(ST3$zqSLmJtNmNrM@1YAP)EJ{v
zC{e<hhY(}L`kEAYh}&wa!GZT{%o*}j<bgEvH01eQWp$ZQ<{ZW{{H9}8?a;NrQ<4kd
zBn;=N{8Z()Q^>wzhJoW2vEmE}|4i}^*~+GoYfTIb!$y!hT2o)YL``DXHV*60O76}=
zHcj+>U9FuDo&2vwUm{l#1vKR0I!_9=dQO^laFl%S_|H;LF)mT?c)Ss<;HTa+<rACN
GmiP~vE*Xpf

diff --git a/dataobjs.py b/dataobjs.py
index e0da239..fb0b62f 100644
--- a/dataobjs.py
+++ b/dataobjs.py
@@ -5,6 +5,9 @@ import random
 
 from generic import PesterIcon
 from parsetools import timeDifference, convertTags
+from mispeller import mispeller
+
+_upperre = re.compile(r"upper\(([\w\\]+)\)")
 
 class Mood(object):
     moods = ["chummy", "rancorous", "offline", "pleasant", "distraught", 
@@ -32,6 +35,7 @@ class Mood(object):
             return PesterIcon(theme["main/chums/moods/chummy/icon"])
         return PesterIcon(f)
 
+
 class pesterQuirk(object):
     def __init__(self, quirk):
         if type(quirk) != dict:
@@ -51,7 +55,13 @@ class pesterQuirk(object):
                 return string
             if not last and len(fr) > 0 and fr[len(fr)-1] == "$":
                 return string
-            return re.sub(fr, self.quirk["to"], string)
+            def regexprep(mo):
+                to = self.quirk["to"]
+                def upperrep(m):
+                    return mo.expand(m.group(1)).upper()
+                to = _upperre.sub(upperrep, to)
+                return mo.expand(to)
+            return re.sub(fr, regexprep, string)
         elif self.type == "random":
             fr = self.quirk["from"]
             if not first and len(fr) > 0 and fr[0] == "^":
@@ -62,6 +72,17 @@ class pesterQuirk(object):
                 choice = random.choice(self.quirk["randomlist"])
                 return mo.expand(choice)
             return re.sub(self.quirk["from"], randomrep, string)
+        elif self.type == "spelling":
+            percentage = self.quirk["percentage"]/100.0
+            words = string.split(" ")
+            newl = []
+            for w in words:
+                p = random.random()
+                if p < percentage:
+                    newl.append(mispeller(w))
+                else:
+                    newl.append(w)
+            return " ".join(newl)
 
     def __str__(self):
         if self.type == "prefix":
@@ -74,6 +95,8 @@ class pesterQuirk(object):
             return "REGEXP: %s REPLACED WITH %s" % (self.quirk["from"], self.quirk["to"])
         elif self.type == "random":
             return "REGEXP: %s RANDOMLY REPLACED WITH %s" % (self.quirk["from"], [str(r) for r in self.quirk["randomlist"]])
+        elif self.type == "spelling":
+            return "MISPELLER: %d%%" % (self.quirk["percentage"])
 
 class pesterQuirks(object):
     def __init__(self, quirklist):
@@ -91,6 +114,7 @@ class pesterQuirks(object):
         replace = [q for q in self.quirklist if
                    q.type=='replace' or q.type=='regexp']
         random = [q for q in self.quirklist if q.type=='random']
+        spelling = [q for q in self.quirklist if q.type=='spelling']
         
         newlist = []
         for (i, o) in enumerate(lexed):
@@ -104,6 +128,8 @@ class pesterQuirks(object):
                 continue
             lastStr = (i == len(lexed)-1)
             string = o
+            for s in spelling:
+                string = s.apply(string)
             for r in random:
                 string = r.apply(string, first=(i==0), last=lastStr)
             for r in replace:
diff --git a/dataobjs.pyc b/dataobjs.pyc
index 670a7cc8550f60460c0f1a069b0cf0b289258734..c548bdb9b1c0874f5fa41abbd8f32b5db0fb948d 100644
GIT binary patch
delta 4536
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

delta 3765
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

diff --git a/generic.py b/generic.py
index ad9a8a8..fd77ad6 100644
--- a/generic.py
+++ b/generic.py
@@ -1,4 +1,13 @@
 from PyQt4 import QtGui, QtCore
+from datetime import timedelta
+
+class mysteryTime(timedelta):
+    def __sub__(self, other):
+        return self
+    def __eq__(self, other):
+        return (type(other) is mysteryTime)
+    def __neq__(self, other):
+        return (type(other) is not mysteryTime)
 
 class PesterList(list):
     def __init__(self, l):
diff --git a/generic.pyc b/generic.pyc
index 3b026d6315651c51eaca35a1ca88fa11262bc9d4..2fe98c5c28b953143b0b74025b2ce7ca330e59d9 100644
GIT binary patch
delta 1065
zcma)5OHUL*5U!rb?#%AYG6<~V`T{u&4`VRI7-J&pg{WX?h$xBatUHa4?jkZxlmw#*
zCZ4fxdeO574tply4|wow!p)QMVoW@Ep{j!uG#=cfYrE^KuJ5brnxD0;zS^hnVd>iR
zt;q)L{apMX$CbU`s2zR|kXZ20hNc7a4zR=q>A(Vm#DSLp>j1asT}WJz1>-H`-XbJL
zkPK4K0A3FGkoX2D8K9H{Wk|{f2n-Mq5E_OMk`QL%%EsINvoS+$$|sYyWFniYuF807
zt!7Ftug;<~FNH!c<H}Cz5vw+dm0(INgU`e^x*HZ6S`>E$SLUEu1EeC)RE!2<3Qz=O
zvbmtBJCD?TxvWQ>bM+#ggveIz3PC_dvB2`YbToM*+$c=VV4Z<t@W9JC^7LwTNpg~9
z7&$R=S8ucPcT@rQLdeHL5aIu`_<yi)y8KTDy&bsSLM##kb#{*-cJ&)JP~;xn^YuGt
zyo>aiUXY{$^DW=n*m_nrYOyYWCidmRfDq|os)Pv9^E(+`<s~xoT)czwxdCp2*Vc~T
zK|T_wzgn+cI(6zN_8RNaKkU=xDxS@oaECggUocm<9B=p_`ZLM_ti&po%?_{%i%skH
zF(J&47&>}~sQty+Wc_`(&8RZ4dRY$(nHh<F0td~FqZn|a{j0EPv5xi!{|t+U(Zff`
zoFY@v-%2-);6Xi6{ya8{PDObyH5zhB$%K!QhuWIrfZ}Rpyo+2UQ^}`_SM^-5!Y1^`
z;8^sR>{$}gJ%o`ojAlNu>&K_!ioOvZx=K7rT}k>BI8BmyUX!_*W{Oj5cqbV%fz<fv
l>j=!H$vvq!6~{?1A3~msrmZ_+7}2#Vi>#_wb$X*-Zx?*_sK5XK

delta 559
zcmZ9I&r2Io5Xa~3?@e5H>0vbnnyP6H2rZOQyomAMhUOI_?PV$17g<P)xKA*&J+u|P
zRtBWdgEy}^<m{n;fp{+XN7#c`XC5U57iM<&erDcx-n&@7t=F$^qKbOae>H%ApF{r+
zMfvHZzBIHz*)SB4+i(Q%9pLRd2XY6LfWkGvodFMW&j8;5e+B}`0|P<>!WpPQUV%5Q
z>dEgF{APcNHJg`eG}MBM5q=dLwScNDD?S!F%M7+i0MWA1v74BOn=T7BPMqt=qspA2
z$9oD--D8)P09U-vBE~cCnMm-`>xp?>_LmZ$nB?OncgYmrhaESh(x3kDCqgV@CrqpV
zyH-uZ0yQj5&%=o&ylH>#xkw)K^b<~NoLu}F^^Nf({2Tpgual_RW_vJDds^l4DJyJL
zXthuAp_CCzd_AoWwM@{855yK8#t-jr+2tj&CUrI_N*?h<*yy&ZJnT|>J?`nYqyi+r
wqB(U`lv?sT$qFa-);!RANnoeQca@fWG0DryCV6b(ujIiTubo<{Q%h>W9bdF#P5=M^

diff --git a/irc.py b/irc.py
index 93f7a49..7c49931 100644
--- a/irc.py
+++ b/irc.py
@@ -32,8 +32,24 @@ class PesterIRC(QtCore.QObject):
     @QtCore.pyqtSlot(QtCore.QString, QtCore.QString)
     def sendMessage(self, text, handle):
         h = unicode(handle)
+        textl = [unicode(text)]
+        def splittext(l):
+            if len(l[0]) > 400:
+                space = l[0].rfind(" ", 0,400)
+                if space == -1:
+                    space = 400
+                a = l[0][0:space]
+                b = l[0][space:]
+                if len(b) > 0:
+                    return [a] + splittext([b])
+                else:
+                    return [a]
+            else:
+                return l
+        textl = splittext(textl)
         try:
-            helpers.msg(self.cli, h, text)
+            for t in textl:
+                helpers.msg(self.cli, h, t)
         except socket.error:
             self.setConnectionBroken()
     @QtCore.pyqtSlot(QtCore.QString, bool)
diff --git a/irc.pyc b/irc.pyc
index e4a65a510087af4df768c7fa422ef6360a2a92cd..4fd91eb3fa2f3cebe8d4ab346ef209f4a4d81f40 100644
GIT binary patch
delta 2436
zcma)7T}+#06n@|SvC<Y8T`6oh*j88tS_aJFU^*Dvm>VMb*v1maW@!tQl@{p7oC+g@
z={Ako-0^2&F3}6)g?gbx6TO@9#v9ENV>B@)i!sKSxTrVI3+H)G`RSrDBYaQJciwZJ
z_c`Z1?^hc7dL-}0@1Fcm8;`u7_uHxhhf>PPkCmUyc^WS%Jusxzv`w8;YEY|~R?jJQ
zL8<dfP1)3(EIn1LP6hC~yT4pb+m)$R!lI^>N?6qt|J&7^Rq63I)kk6H{WBJ(?v83k
z8$Wh_y!>R|WH6akVUsduj#<=*O{Hg*Ui2l{XT>V7FypjVQ*7JRh()FIm1ZxyQhGU_
zBROEhv}ge-zg0}nSY;b4#IqAy_&CL)xK31Mg~4n7-bH6`$}W_>F{OHg(A%A0P>D-i
z1J|llW#SJ11yPuZ#wFt^6LAxRiBv3zDkUr_&Ol}?5{-)^A~+BPhl#Fd#*zusjGr>;
zMs@v$8ukR>UBjTXUzcf*&eyATf%a;j#bu$R&WE*wt~$%hg&LVj;WUFt5n`i;&Xk6z
z&1a)q&LW?1S=_o%7kb><s`HdXuc!R{&t0{gVL+@=N8jgHIzlkRWOG&PE!5D|OhqA^
zD`Q3`%#L*GWV)HgUGr;mk`V3(EGFvWQb}xe##1p#X`@;92TQyyo(bJa?|H84I!YIm
zFS%bT@apZn-8P5uAd~gb&4M3&b<5ma@7lmicYO9mbttgD$ff(JwdkI7HKQl)fn+**
zA|C4)o*X?+kFCCPFBLTxdsxO~Dkpc4bJx-7;%LQkN90ISk<oZ2w=I{w!+Mkw-shJJ
zzU@7#O**`0YW+$kPGKaSNaZGyF7`S)Q2uT?jW%DQewuoGr*$oT>GLnq{VU2wZ6z*!
zhPp~#Y`=Sl6N%`F+#SGO!5}kkphUw5$ZiS?bI|HU-l0r<;yfMmf5N+$l~!)ao;hNK
zArF=?NOBLqn(#%_qoa{jj7vzA_UTJ>z4R^pIt`VL_B0^`bq}P|Nn;xuMl+xVfJrcR
z0@?uWfIWatz$1VIfJXrb0f!d?Yqx0aUpTa`#b!5fjp((CHr-F(RFsdjB4h_3JMV0n
z`0_=Q3BJ0<09GP!;ug!LG}utaF~D)a6AVE&EU9ueTcSQX97!26uF|?zI#xNW-(9#_
z>DNtz2p<Q?uKQq30E7n@Gu!VKb#+v`@d206O=9^Zy|HSC8;yK2p5$J}zomtZABTmc
z3;}Tfwg{q}thQ-by#T1>%RRs8p#FhwZJOCW3`aMEXdj>Cj}OSxgM-OLDxT#?B1XuE
zV2S>IdOPsAeU9IMqP(gBM|OqMRb{$^E>v~cyLjmrx>0pS57S8XeGi@G_y3^-F<PB7
zd7@Q@=UKY7d53*JFaJvR&6gb_dLLce90>oXwq-Ku^78Q*9pLe!>woZ*S;e4qiF{Oz
zZrT;>tXM8EN5?si%HDt;(ScF^lYS0<b`(0YQ^Vhm*noi=GpM2}(^8d@wo1pdV<J-J
zP~041ya14{_QR5{BG(WNQ{=1(@SP3U9MXT$*_sdS#wK2*owY3+GKd-lqyPa1Ike$O
zCSsZs#zmU1t@6pCOAl8H*hOE}_E@y0>N<1RMI`3|L`4)9R0PE*U0dOhbErcIF_`$F
z8%t8Vdn^AY6j+>^DnrA1FI@;Vxg<$uKP8{3ze65Np(aoGO#M6v_JRO?h>VT#??O(e
zb21Uwk^K?4!nT)ghht%6X2r%}iCAgbidflKbiRVk<)$PP8Iw2iFMLtotk<GlE0;cd
z{X+1CsiL7q@233?ow}SZH-x+T;64I)25=fM3z!3R0Wg#XCd$BAWbfC@uwDgR1wg-X
ajogiU^gCoU&bZ|0X5bCcca0zEYySXldAsuf

delta 2046
zcma)7ZA_b06n<}k7I|C1mC{l`zS>f{QOaNz7@Lev*$gPTjG^+86x!Ls+mF$gxhXQ8
zKW20+%E_Y9C4M9%`{NHKnrMvC#KbI%QDUM$O#E6*{7TIB&-g>{bKgOcEQX|ga_+h3
zoO{l5&$;i{v-GHC{idzt&F_cbw%jNV6)K8i5&wwz=Y|C6in3@@o?*(91<Dz>qBA9F
zQWg~@S)eS69}Vqlql=X#bcfnq3ukVF6C^!;TIUW3OhAGTxjX5KTA`MRm14580_LW5
z^{Uz=mR!1eXw_P8_G0a$YgQlg(~tHrwb)8oGj-Wsac?n&krQys{12N8=C1wJS6a+M
zbhPxHjYzC)o`p#-`y}ky@RA9pGMSiOBvhxO+CuzRAXwB1@S7l^7~V!F1L2~e5c}v#
z`Om@4C_I2|BLPU#uK<$a2T7Jtt_pD>8;k1kNJh)d50GisPO1^bo9$)nK?+n<)0izv
zEB2ZlkYGQ;jtiHix=p@hndxXMp8F4JpH(E-B!wK$ZBX^GV}iw~wsJ9?cg5ArW|HZx
zo~UeFwcXJ5$P2SL%h)VAolD!IWTW%?j-yD<wD<`<l8C0$aqT48UCXSA-f%fLvi->A
zQjKGAHf}${PLsFl17Y?<RefmN&7iN1n~_fUiKPzROeU3zreh-ckb8_hMbEld*#!z#
zr-oZ#g8HX38IA7|0&fL`0B8ul4{$di4A>7i0JsNm2oM3>4;Wngy*k90Wv!;Rr?6N@
zr)cpsjW_hM5xU$^6KRLlUH}f|Xf)j{U`9*E(>i|$$}uR>wYjX8)VUB8ehe@QI8J{z
z)TnTjqsQB+vGE+cytdltWR3}_695_hAfzO%H`&$v!5;dvX`c~5!+wfhFYcu|kIJsn
zW1jbeNhqrT;{ZhSBSnK)@meVSDBw<jho-#8*jKdXJ!_tV;xKjj?sCjPlrbhD$&5y5
z&Np84xLAKf*L>6Un>&8gDx*s(GTC%;W{!8$P;;cHUu=C#mzrN@Qxx>q9(Y2mjcjgv
z1Og#iKBSSRY==eC0=-3jV*5L~>R&PPJxI|OPw@YPNiOBU%bL3p#|dt)i+`?IfWj(S
z6|*r>zBw>Zcbn4qlCa`NTgp7poWIapflnvEo6!V`g;Z>sqsAPn@aB5FIeu73vI@Ty
zl1x?Jhg_b6PBJ|LNir?@lsV++^W7dXF*kRQvft>)o_EdisjeqeYfr;09AbbtU|N8j
zmP9lc)%AIPo+ewp4te3S?tBGZ^iu1v>4rkTw(9-o;VdUlrtvVAvT3AF(w2`Q3Gl$=
zc^ro)IIH2qQI3yBJRQrNkdN433SAE-ST7B>b*R!E-x(g4uTOn-p{gZwdQKP5%|8l#
z+4gkX3buO%NG7A%tcbOx3$}!SVYhtnUl3veeHe-b;b^e<2qc-lWHFz<JYQzMj3lh6
z4oQe}ENd^ehnX7$=Es`LIr2j1qo4K$SP$7c2AGvbJA#8lP(J{e2P^>205BfBAJ7Lt
plW}y4(Z&}bT?7yS`SVNkMaRADRdRHmRpn)#g4Ro~b-u@z{{@2idDs8|

diff --git a/logs/chums.js b/logs/chums.js
index e55192a..74ba284 100644
--- a/logs/chums.js
+++ b/logs/chums.js
@@ -1 +1 @@
-{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "lyricalKeraunoscopic": {"color": "#00c000", "handle": "lyricalKeraunoscopic", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "carcinoGeneticist": {"color": "#999999", "handle": "carcinoGeneticist", "mood": "offline"}, "greyscalePacifist": {"color": "#7f7f7f", "handle": "greyscalePacifist", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#ff0000", "handle": "iw", "mood": "offline"}, "insipidTranscient": {"color": "#145064", "handle": "insipidTranscient", "mood": "offline"}, "caffeinatedAnalyst": {"color": "#aa0000", "handle": "caffeinatedAnalyst", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "quintessentialArbalest": {"color": "#999999", "handle": "quintessentialArbalest", "mood": "offline"}, "noSense": {"color": "#1d0059", "handle": "noSense", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "grimAuxiliatrix": {"color": "#008141", "handle": "grimAuxiliatrix", "mood": "offline"}, "terminallyCapricious": {"color": "#2b0057", "handle": "terminallyCapricious", "mood": "offline"}, "androidTechnician": {"color": "#0000ff", "handle": "androidTechnician", "mood": "offline"}, "ardentAbettor": {"color": "#c8b670", "handle": "ardentAbettor", "mood": "offline"}, "aceIsm": {"color": "#ffcc66", "handle": "aceIsm", "mood": "offline"}, "apocalypseArisen": {"color": "#a10000", "handle": "apocalypseArisen", "mood": "offline"}, "radicalApologist": {"color": "#ffaa00", "handle": "radicalApologist", "mood": "offline"}, "microMachines": {"color": "#aa00ff", "handle": "microMachines", "mood": "offline"}, "uroborosUnbound": {"color": "#00416a", "handle": "uroborosUnbound", "mood": "offline"}, "arachnidsGrip": {"color": "#005682", "handle": "arachnidsGrip", "mood": "offline"}, "caligulasAquarium": {"color": "#6a006a", "handle": "caligulasAquarium", "mood": "offline"}, "percipientPedestrian": {"color": "#00ffff", "handle": "percipientPedestrian", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "sucroseSaboteur": {"color": "#00e700", "handle": "sucroseSaboteur", "mood": "offline"}, "illuminatedWax": {"color": "#000000", "handle": "illuminatedWax", "mood": "offline"}, "moirailBunp": {"color": "#6a3d0f", "handle": "moirailBunp", "mood": "offline"}, "madLurker": {"color": "#000000", "handle": "madLurker", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "pesterClient3022": {"color": "#336600", "handle": "pesterClient3022", "mood": "offline"}, "hellerificJefferson": {"color": "#3300ff", "handle": "hellerificJefferson", "mood": "offline"}, "DocScratch": {"color": "#ffffff", "handle": "DocScratch", "mood": "offline"}, "recalcitrantDisaster": {"color": "#8b0068", "handle": "recalcitrantDisaster", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "arsenicCatnip": {"color": "#006400", "handle": "arsenicCatnip", "mood": "offline"}, "kaleidoscopicMind": {"color": "#ff6666", "handle": "kaleidoscopicMind", "mood": "offline"}, "zealousScarecrow": {"color": "#00c882", "handle": "zealousScarecrow", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "wovenWay": {"color": "#000000", "handle": "wovenWay", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "elegantDiversion": {"color": "#14b40a", "handle": "elegantDiversion", "mood": "offline"}, "plasmaModerator": {"color": "#5685cc", "handle": "plasmaModerator", "mood": "offline"}, "carcinoGenetecist": {"color": "#7f7f7f", "handle": "carcinoGenetecist", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "oilslickOrchid": {"color": "#743f7e", "handle": "oilslickOrchid", "mood": "offline"}, "acapellaWaterfall": {"color": "#000099", "handle": "acapellaWaterfall", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "anguillaNuntia": {"color": "#ff007f", "handle": "anguillaNuntia", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "lawdEngrish": {"color": "#00ff00", "handle": "lawdEngrish", "mood": "offline"}, "pretentiousFantasia": {"color": "#ff66cf", "handle": "pretentiousFantasia", "mood": "offline"}, "counterRealist": {"color": "#10d985", "handle": "counterRealist", "mood": "offline"}, "maxiumumFatness": {"color": "#3366ff", "handle": "maxiumumFatness", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "metaliAggressive": {"color": "#9289d5", "handle": "metaliAggressive", "mood": "offline"}, "midnightSparrow": {"color": "#ff55ff", "handle": "midnightSparrow", "mood": "offline"}, "magmaExploiter": {"color": "#d90000", "handle": "magmaExploiter", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "utilitarianTurnabout": {"color": "#dd0000", "handle": "utilitarianTurnabout", "mood": "offline"}, "adiosToreador": {"color": "#aa5500", "handle": "adiosToreador", "mood": "offline"}}
\ No newline at end of file
+{"macruralAlchemist": {"color": "#700000", "handle": "macruralAlchemist", "mood": "offline"}, "lyricalKeraunoscopic": {"color": "#00aa00", "handle": "lyricalKeraunoscopic", "mood": "offline"}, "fireSwallow": {"color": "#80bb9a", "handle": "fireSwallow", "mood": "offline"}, "aquaMarinist": {"color": "#00caca", "handle": "aquaMarinist", "mood": "offline"}, "centaursTesticle": {"color": "#000056", "handle": "centaursTesticle", "mood": "offline"}, "mechanicalSpectacle": {"color": "#0000ff", "handle": "mechanicalSpectacle", "mood": "offline"}, "depthPerception": {"color": "#6f3886", "handle": "depthPerception", "mood": "offline"}, "carcinoGeneticist": {"color": "#999999", "handle": "carcinoGeneticist", "mood": "offline"}, "greyscalePacifist": {"color": "#7f7f7f", "handle": "greyscalePacifist", "mood": "offline"}, "aquaticMarinist": {"color": "#00caca", "handle": "aquaticMarinist", "mood": "offline"}, "iw": {"color": "#000000", "handle": "iw", "mood": "offline"}, "insipidTranscient": {"color": "#145064", "handle": "insipidTranscient", "mood": "offline"}, "caffeinatedAnalyst": {"color": "#aa0000", "handle": "caffeinatedAnalyst", "mood": "offline"}, "midnightSparrow": {"color": "#ff55ff", "handle": "midnightSparrow", "mood": "offline"}, "absoluteTranquility": {"color": "#000033", "handle": "absoluteTranquility", "mood": "offline"}, "nitroZealist": {"color": "#ff3737", "handle": "nitroZealist", "mood": "offline"}, "quintessentialArbalest": {"color": "#999999", "handle": "quintessentialArbalest", "mood": "offline"}, "noSense": {"color": "#1d0059", "handle": "noSense", "mood": "offline"}, "agogPorphyry": {"color": "#522d80", "handle": "agogPorphyry", "mood": "offline"}, "grimAuxiliatrix": {"color": "#008141", "handle": "grimAuxiliatrix", "mood": "offline"}, "terminallyCapricious": {"color": "#2b0057", "handle": "terminallyCapricious", "mood": "offline"}, "androidTechnician": {"color": "#0000ff", "handle": "androidTechnician", "mood": "offline"}, "ardentAbettor": {"color": "#c8b670", "handle": "ardentAbettor", "mood": "offline"}, "aceIsm": {"color": "#ffcc66", "handle": "aceIsm", "mood": "offline"}, "apocalypseArisen": {"color": "#a10000", "handle": "apocalypseArisen", "mood": "offline"}, "radicalApologist": {"color": "#ffaa00", "handle": "radicalApologist", "mood": "offline"}, "microMachines": {"color": "#aa00ff", "handle": "microMachines", "mood": "offline"}, "uroborosUnbound": {"color": "#00416a", "handle": "uroborosUnbound", "mood": "offline"}, "arachnidsGrip": {"color": "#005682", "handle": "arachnidsGrip", "mood": "offline"}, "caligulasAquarium": {"color": "#6a006a", "handle": "caligulasAquarium", "mood": "offline"}, "percipientPedestrian": {"color": "#00ffff", "handle": "percipientPedestrian", "mood": "offline"}, "tentacleTherapist": {"color": "#cc66ff", "handle": "tentacleTherapist", "mood": "offline"}, "sucroseSaboteur": {"color": "#00e700", "handle": "sucroseSaboteur", "mood": "offline"}, "illuminatedWax": {"color": "#000000", "handle": "illuminatedWax", "mood": "offline"}, "moirailBunp": {"color": "#6a3d0f", "handle": "moirailBunp", "mood": "offline"}, "madLurker": {"color": "#000000", "handle": "madLurker", "mood": "offline"}, "testOut": {"color": "#c760cc", "handle": "testOut", "mood": "offline"}, "pesterClient3022": {"color": "#336600", "handle": "pesterClient3022", "mood": "offline"}, "hellerificJefferson": {"color": "#3300ff", "handle": "hellerificJefferson", "mood": "offline"}, "DocScratch": {"color": "#ffffff", "handle": "DocScratch", "mood": "offline"}, "recalcitrantDisaster": {"color": "#8b0068", "handle": "recalcitrantDisaster", "mood": "offline"}, "superGhost": {"color": "#800564", "handle": "superGhost", "mood": "offline"}, "arsenicCatnip": {"color": "#006400", "handle": "arsenicCatnip", "mood": "offline"}, "kaleidoscopicMind": {"color": "#ff6666", "handle": "kaleidoscopicMind", "mood": "offline"}, "zealousScarecrow": {"color": "#00c882", "handle": "zealousScarecrow", "mood": "offline"}, "captainCaveman": {"color": "#7c414e", "handle": "captainCaveman", "mood": "offline"}, "gamblingGenocider": {"color": "#00ff00", "handle": "gamblingGenocider", "mood": "offline"}, "cuttlefishCuller": {"color": "#77003c", "handle": "cuttlefishCuller", "mood": "offline"}, "wovenWay": {"color": "#000000", "handle": "wovenWay", "mood": "offline"}, "masterG": {"color": "#77003c", "handle": "masterG", "mood": "offline"}, "elegantDiversion": {"color": "#14b40a", "handle": "elegantDiversion", "mood": "offline"}, "plasmaModerator": {"color": "#5685cc", "handle": "plasmaModerator", "mood": "offline"}, "carcinoGenetecist": {"color": "#7f7f7f", "handle": "carcinoGenetecist", "mood": "offline"}, "marineAquist": {"color": "#00caca", "handle": "marineAquist", "mood": "offline"}, "remoteBloodbath": {"color": "#c70000", "handle": "remoteBloodbath", "mood": "offline"}, "oilslickOrchid": {"color": "#743f7e", "handle": "oilslickOrchid", "mood": "offline"}, "acapellaWaterfall": {"color": "#000099", "handle": "acapellaWaterfall", "mood": "offline"}, "gallowsCalibrator": {"color": "#008282", "handle": "gallowsCalibrator", "mood": "offline"}, "rageInducer": {"color": "#00ffff", "handle": "rageInducer", "mood": "offline"}, "anguillaNuntia": {"color": "#ff007f", "handle": "anguillaNuntia", "mood": "offline"}, "doctectiveMiracles": {"color": "#999900", "handle": "doctectiveMiracles", "mood": "offline"}, "obliviousCrafter": {"color": "#fd36b1", "handle": "obliviousCrafter", "mood": "offline"}, "greenZephyr": {"color": "#00ca40", "handle": "greenZephyr", "mood": "offline"}, "lawdEngrish": {"color": "#00ff00", "handle": "lawdEngrish", "mood": "offline"}, "pretentiousFantasia": {"color": "#ff66cf", "handle": "pretentiousFantasia", "mood": "offline"}, "counterRealist": {"color": "#10d985", "handle": "counterRealist", "mood": "offline"}, "maxiumumFatness": {"color": "#3366ff", "handle": "maxiumumFatness", "mood": "offline"}, "schlagzeugGator": {"color": "#61821f", "handle": "schlagzeugGator", "mood": "offline"}, "metaliAggressive": {"color": "#9289d5", "handle": "metaliAggressive", "mood": "offline"}, "pesterClient394": {"color": "#ff3737", "handle": "pesterClient394", "mood": "offline"}, "magmaExploiter": {"color": "#d90000", "handle": "magmaExploiter", "mood": "offline"}, "gardenGnostic": {"color": "#00ff00", "handle": "gardenGnostic", "mood": "offline"}, "unknownTraveler": {"color": "#006666", "handle": "unknownTraveler", "mood": "offline"}, "utilitarianTurnabout": {"color": "#dd0000", "handle": "utilitarianTurnabout", "mood": "offline"}, "adiosToreador": {"color": "#aa5500", "handle": "adiosToreador", "mood": "offline"}}
\ No newline at end of file
diff --git a/memos.py b/memos.py
index ec8bb6b..6562550 100644
--- a/memos.py
+++ b/memos.py
@@ -5,12 +5,15 @@ from PyQt4 import QtGui, QtCore
 from datetime import time, timedelta, datetime
 
 from dataobjs import PesterProfile, Mood, PesterHistory
-from generic import PesterIcon, RightClickList
+from generic import PesterIcon, RightClickList, mysteryTime
 from convo import PesterConvo, PesterInput, PesterText, PesterTabWindow
 from parsetools import convertTags, addTimeInitial, timeProtocol, \
     lexMessage, colorBegin, colorEnd, mecmd
 
+
 def delta2txt(d, format="pc"):
+    if type(d) is mysteryTime:
+        return "?"
     if format == "pc":
         sign = "+" if d >= timedelta(0) else "-"
     else:
@@ -34,6 +37,8 @@ def delta2txt(d, format="pc"):
 
 def txt2delta(txt):
     sign = 1
+    if txt[0] == '?':
+        return mysteryTime()
     if txt[0] == '+':
         txt = txt[1:]
     elif txt[0] == '-':
@@ -51,7 +56,11 @@ def txt2delta(txt):
     return sign*timed
 
 def pcfGrammar(td):
-    if td > timedelta(0):
+    if type(td) is mysteryTime:
+        when = "???"
+        temporal = "???"
+        pcf = "?"
+    elif td > timedelta(0):
         when = "FROM NOW"
         temporal = "FUTURE"
         pcf = "F"
@@ -109,14 +118,14 @@ class TimeTracker(list):
         self.current = self.index(timed)
     def addRecord(self, timed):
         (temporal, pcf, when) = pcfGrammar(timed - timedelta(0))
-        if pcf == "C":
+        if pcf == "C" or pcf == "?":
             return
         if timed in self.timerecord[pcf]:
             return
         self.timerecord[pcf].append(timed)
     def getRecord(self, timed):
         (temporal, pcf, when) = pcfGrammar(timed - timedelta(0))
-        if pcf == "C":
+        if pcf == "C" or pcf == "?":
             return 0
         if len(self.timerecord[pcf]) > 1:
             return self.timerecord[pcf].index(timed)+1
@@ -170,6 +179,10 @@ class TimeInput(QtGui.QLineEdit):
     def setSlider(self):
         value = unicode(self.text())
         timed = txt2delta(value)
+        if type(timed) is mysteryTime:
+            self.timeslider.setValue(0)
+            self.setText("?")
+            return
         sign = 1 if timed >= timedelta(0) else -1
         abstimed = abs(txt2delta(value))
         index = 50
@@ -254,7 +267,7 @@ class MemoText(PesterText):
         if chum is not me:
             if parent.times.has_key(chum.handle):
                 time = parent.times[chum.handle]
-                if not time.getTime():
+                if time.getTime() is None:
                     # MY WAY OR THE HIGHWAY
                     time.addTime(timedelta(0))
             else:
diff --git a/memos.pyc b/memos.pyc
index 3061b672f878748ad8ea202d7dfcb28c659b2996..e3f1eb4923bc8447aea0a2ddb424c073f669bb99 100644
GIT binary patch
delta 7408
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
UY+rV^!?(|u>ibCi;AzMI0Xt5rssI20

delta 7021
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
Ao&W#<

diff --git a/menus.py b/menus.py
index f7ff4e6..7e221a8 100644
--- a/menus.py
+++ b/menus.py
@@ -38,6 +38,45 @@ class PesterQuirkList(QtGui.QListWidget):
         if i >= 0:
             self.takeItem(i)
 
+class MispellQuirkDialog(QtGui.QDialog):
+    def __init__(self, parent):
+        QtGui.QDialog.__init__(self, parent)
+        self.setWindowTitle("MISPELLER")
+        layout_1 = QtGui.QHBoxLayout()
+        zero = QtGui.QLabel("1%", self)
+        hund = QtGui.QLabel("100%", self)
+        self.slider = QtGui.QSlider(QtCore.Qt.Horizontal, self)
+        self.slider.setMinimum(1)
+        self.slider.setMaximum(100)
+        self.slider.setValue(50)
+        layout_1.addWidget(zero)
+        layout_1.addWidget(self.slider)
+        layout_1.addWidget(hund)
+
+        self.ok = QtGui.QPushButton("OK", self)
+        self.ok.setDefault(True)
+        self.connect(self.ok, QtCore.SIGNAL('clicked()'),
+                     self, QtCore.SLOT('accept()'))
+        self.cancel = QtGui.QPushButton("CANCEL", self)
+        self.connect(self.cancel, QtCore.SIGNAL('clicked()'),
+                     self, QtCore.SLOT('reject()'))
+        layout_ok = QtGui.QHBoxLayout()
+        layout_ok.addWidget(self.cancel)
+        layout_ok.addWidget(self.ok)
+
+        layout_0 = QtGui.QVBoxLayout()
+        layout_0.addLayout(layout_1)
+        layout_0.addLayout(layout_ok)
+
+        self.setLayout(layout_0)
+    def getPercentage(self):
+        r = self.exec_()
+        if r == QtGui.QDialog.Accepted:
+            retval = {"percentage": self.slider.value()}
+            return retval
+        else:
+            return None
+
 class RandomQuirkDialog(MultiTextDialog):
     def __init__(self, parent):
         QtGui.QDialog.__init__(self, parent)
@@ -138,6 +177,10 @@ class PesterChooseQuirks(QtGui.QDialog):
         self.connect(self.addRandomReplaceButton, QtCore.SIGNAL('clicked()'),
                      self, QtCore.SLOT('addRandomDialog()'))
 
+        self.addMispellingButton = QtGui.QPushButton("MISPELLER", self)
+        self.connect(self.addMispellingButton, QtCore.SIGNAL('clicked()'),
+                     self, QtCore.SLOT('addSpellDialog()'))
+
         layout_1 = QtGui.QHBoxLayout()
         layout_1.addWidget(self.addPrefixButton)
         layout_1.addWidget(self.addSuffixButton)
@@ -145,6 +188,7 @@ class PesterChooseQuirks(QtGui.QDialog):
         layout_2 = QtGui.QHBoxLayout()
         layout_2.addWidget(self.addRegexpReplaceButton)
         layout_2.addWidget(self.addRandomReplaceButton)
+        layout_2.addWidget(self.addMispellingButton)
 
         self.removeSelectedButton = QtGui.QPushButton("REMOVE", self)
         self.connect(self.removeSelectedButton, QtCore.SIGNAL('clicked()'),
@@ -240,6 +284,16 @@ class PesterChooseQuirks(QtGui.QDialog):
         item = PesterQuirkItem(quirk, self.quirkList)
         self.quirkList.addItem(item)
         #self.quirkList.sortItems()
+    @QtCore.pyqtSlot()
+    def addSpellDialog(self):
+        vdict = MispellQuirkDialog(self).getPercentage()
+        if vdict is None:
+            return
+        vdict["type"] = "spelling"
+        quirk = pesterQuirk(vdict)
+        item = PesterQuirkItem(quirk, self.quirkList)
+        self.quirkList.addItem(item)
+        #self.quirkList.sortItems()
 
 class PesterChooseTheme(QtGui.QDialog):
     def __init__(self, config, theme, parent):
diff --git a/menus.pyc b/menus.pyc
index 271db3aa93100ba4cc33de382be149fd49d85c97..78b466434907c5404b9b1229ed53501bd3a368dd 100644
GIT binary patch
delta 5545
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
P{GP*}M$fos)KmIjOFA(~

delta 4176
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
D*wr?G

diff --git a/mispeller.py b/mispeller.py
new file mode 100644
index 0000000..b8240e3
--- /dev/null
+++ b/mispeller.py
@@ -0,0 +1,60 @@
+import random
+
+kbloc = [[x for x in "1234567890-="],
+         [x for x in "qwertyuiop[]"],
+         [x for x in "asdfghjkl:;'"],
+         [x for x in "zxcvbnm,.>/?"]]
+kbdict = {}
+for (i, l) in enumerate(kbloc):
+    for (j, k) in enumerate(l):
+        kbdict[k] = (i, j)
+
+sounddict = {"a": "e", "b": "d", "c": "k", "d": "g", "e": "eh",
+             "f": "ph", "g": "j", "h": "h", "i": "ai", "j": "ge",
+             "k": "c", "l": "ll", "m": "n", "n": "m", "o": "oa",
+             "p": "b", "q": "kw", "r": "ar", "s": "ss", "t": "d",
+             "u": "you", "v": "w", "w": "wn", "x": "cks", "y": "uy", "z": "s"}
+             
+
+def mispeller(word):
+    if len(word) <= 6:
+        num = 1
+    else:
+        num = random.choice([1,2])
+    wordseq = range(0, len(word))
+    random.shuffle(wordseq)
+    letters = wordseq[0:num]
+    def mistype(string, i):
+        l = string[i]
+        if not kbdict.has_key(l):
+            return string
+        lpos = kbdict[l]
+        newpos = lpos
+        while newpos == lpos:
+            newpos = ((lpos[0] + random.choice([-1, 0, 1])) % len(kbloc),
+                      (lpos[1] + random.choice([-1,0,1])) % len(kbloc[0]))
+        string = string[0:i]+kbloc[newpos[0]][newpos[1]]+string[i+1:]
+        return string
+    def transpose(string, i):
+        j = (i + random.choice([-1,1])) % len(string)
+        l = [c for c in string]
+        l[i], l[j] = l[j], l[i]
+        return "".join(l)
+    def randomletter(string, i):
+        string = string[0:i+1]+random.choice("abcdefghijklmnopqrstuvwxyz")+string[i+1:]
+        return string
+    def randomreplace(string, i):
+        string = string[0:i]+random.choice("abcdefghijklmnopqrstuvwxyz")+string[i+1:]
+        return string
+    def soundalike(string, i):
+        try:
+            c = sounddict[string[i]]
+        except:
+            return string
+        string = string[0:i]+c+string[i+1:]
+        return string
+    func = random.choice([mistype, transpose, randomletter, randomreplace,
+                          soundalike])
+    for i in letters:
+        word = func(word, i)
+    return word
diff --git a/mispeller.pyc b/mispeller.pyc
new file mode 100644
index 0000000000000000000000000000000000000000..c5eb90bc0e4f1b744cbda37171609d379461fbad
GIT binary patch
literal 2929
zcmcIlTW=dx5T3K^d+fHPByM_7TM{?TrRl|OArufuJkbZ|A(hjpa`v3q8?Se5@4B%o
zr!VDi@Wf9*;$I-aU*QkHH**{ZqzXhNY@eAqGjlHU&7ARXzn2Q?-OKMhntaZIe~A(Q
zsE9OvirPeVq9#$Qu1Gud&0dM>4jDzpq1j%Uc9pfdq}{32wbsY9>so7ybZTl%S?f0K
zrmQthIz6?ft+hwHX=<jZo}m`*kfq_bWO8IO^j^XD8NG6-o~L?&hAUzySi@B@%uu~Z
zCQoLD4shEnnIdiVex{w?546*|Ogck4OI4jCod+wBo&hTo6jfbfb5)-seID!rL0{D$
z5q?!YOZp<%#{_*9i?Fn+=Sa_kl}TR$yF`$xdV%z1usrE2U{^_B1G`T82G~u~i(okY
z7T9glcfdX&y#%&QkgB>u`YzZC>3d*{q*tk0$IaI0d%%IaDcY{ABU%0*_`HaV5H}w@
zeDt{b<mt2fYoCjvcVzm>Xy8ZP-91q>VtvqT9kzo{KU)^X+oAVnKkTfoKi~KwLDtC#
zZ3xvu_l35FdP19t!=5c+-InMMgdPgDhK4T_U%Z+|SP+QL(op1%7$SROB&x2c+D9_!
z$)wSjNna*$EE7wU#KmPs(Li*T+Ldp_`6v_zuWj9jq8yCG+tRll2R?(5#rPT{{uLx4
z8WR^4pgvR-6-eO$94iXvNnyF~@Pk0rHy!qZ0SBSXr|aIs+adN$(O7&G7(B*`7LVbZ
z=3E}*ZDd5iGsud7;>?MV<?>{ooNVLJ7>m<1&d@kZ;~X{9a&n%A*J#YoZ;p-&G|uzI
z$9NF908#HJ+QEFgQb15I{0yki0ptE4804{(#$ekvM*Is1@1bacLy#3Vgl?J?@1{6R
z2WFQ~Mi9e8xt&Xg4n?ovgaEM|aQl!DH-H3IF5kGE04BNnJiEF7?8e(*(L7!<&gnfM
z#qmJPIAR-s!Y&KUvDHG^-W+oIMi~I`bt@@E^g^PQ2O|hnINpRwdtdurl5qZ8jreuj
zj6~gUggWYo=(Qr>Gg3-{32`bf3L>w<l6b^P-w&I$66UoFtmGquZWN0(G)E9CP?3;$
z1=2<<>X;3UW16PFaTN928(kA8rth@|osEtkcTEtO{(5&LSA!xMb<Gv5jOTeLRZtgH
z8Z@I^Dyd~vRclJJ$w5uC8DavgY#KQa&ZK6`$PUn9aFJ&2@|;eRUJR&_8(=!yTc>wO
zF@VMoDQ5<}9m}_@b_;ML(U@Sj6S%oG3DP(kaWf#byG%Iv+C2~f=`iv`$wh6A^@1Q5
zs~BJJZtm3>WC8W;0Ool^ARQwOW(kux2SVz$T2$98XeZA=o&fh&Kw--ah?N&7_}L1E
z2_UfkgEhtvEV&HQ*!Q$S&-KxCJ7LuA_2Xpl=4d#2TjAqQ;jq&w0A~-B{|Rj21|~r*
zG0ZVTPio}@adIlAah}8|-RfW7QSC8S+IRFnMZ$$(Bk7xN(C`fBWD?4f4TXC@=TTDj
z9KvXJ(tx={xq0n`IZ{e`*2~j4QO76Y{Vj#O-=s}&3M-OFE}b|UgqoW~g<bwqs9c(7
zPZpQCY~2X_w%Ozv=Z}=DW--zzP3bW5SWb&Y`j4~?X$)~|aBvWq3jc@6qd_at(yPKj
zM?6>&o1VzFEaKXIc-I~=sWN%O<Qa(Ua4-lxd5LF_jbWSiu#1?)w?If;R0U^F&8ZT;
z`I&q=@8X-CRYjGh46K#&@UpQ!Wa&1@q!m2an+Ok2ghzX|Rd!ltCqB_2WYcdX=Cl*n
z80DIDpQkK+1#%jeNdL7R=di_AC(?t!Jm(sTZ-Nw^>x#d3(2q-0lyS*fLW|+=n)@dU
C-3&nh

literal 0
HcmV?d00001

diff --git a/parsetools.py b/parsetools.py
index cc9f8b9..474034a 100644
--- a/parsetools.py
+++ b/parsetools.py
@@ -3,6 +3,8 @@ from copy import copy
 from datetime import timedelta
 from PyQt4 import QtGui
 
+from generic import mysteryTime
+
 _ctag_begin = re.compile(r'(?i)<c=(.*?)>')
 _gtag_begin = re.compile(r'(?i)<g[a-f]>')
 _ctag_end = re.compile(r'(?i)</c>')
@@ -183,6 +185,8 @@ def addTimeInitial(string, grammar):
 
 def timeProtocol(cmd):
     dir = cmd[0]
+    if dir == "?":
+        return mysteryTime(0)
     cmd = cmd[1:]
     cmd = re.sub("[^0-9:]", "", cmd)
     try:
@@ -195,6 +199,8 @@ def timeProtocol(cmd):
     return timed
 
 def timeDifference(td):
+    if type(td) is mysteryTime:
+        return "??:?? FROM ????"
     if td < timedelta(0):
         when = "AGO"
     else:
diff --git a/parsetools.pyc b/parsetools.pyc
index 35887e8125adc659e516fccb344d3ed508e9dc3f..b589134de2395b47149877edf4287fbf1fbae439 100644
GIT binary patch
delta 2985
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
G-})0YaRL4S

delta 2732
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
To2}9nu&OuP2OLh}6mHA^->}U2

diff --git a/pesterchum.js b/pesterchum.js
index ff954a3..e8e728a 100644
--- a/pesterchum.js
+++ b/pesterchum.js
@@ -1 +1 @@
-{"tabs": true, "soundon": true, "chums": ["unknownTraveler", "tentacleTherapist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist", "percipientPedestrian", "asceticClinician"], "defaultprofile": "ghostDunk", "block": []}
\ No newline at end of file
+{"tabs": true, "soundon": true, "chums": ["unknownTraveler", "tentacleTherapist", "vaginalEngineer", "mechanicalSpectacle", "carcinoGeneticist", "schlagzeugGator", "gamblingGenocider", "gardenGnostic", "superGhost", "centaursTesticle", "arachnidsGrip", "grimAuxiliatrix", "remoteBloodbath", "nitroZealist", "greenZephyr", "arsenicCatnip", "adiosToreador", "cuttlefishCuller", "rageInducer", "gallowsCalibrator", "caligulasAquarium", "terminallyCapricious", "illuminatedWax", "aquaMarinist", "elegantDiversion", "moirailBunp", "uroborosUnbound", "androidTechnician", "midnightSparrow", "apocalypseArisen", "anguillaNuntia", "oilslickOrchid", "confusedTransient", "pretentiousFantasia", "aquaticMarinist", "lyricalKeraunoscopic", "counterRealist", "ectoBiologist", "percipientPedestrian", "asceticClinician", "doctectiveMiracles", "noSense"], "defaultprofile": "ghostDunk", "block": []}
\ No newline at end of file
diff --git a/pesterchum.py b/pesterchum.py
index b5edad3..91fa78e 100644
--- a/pesterchum.py
+++ b/pesterchum.py
@@ -825,6 +825,7 @@ class PesterWindow(MovingWindow):
         self.closeConversations()
         if hasattr(self, 'trollslum') and self.trollslum:
             self.trollslum.close()
+        self.closeSignal.emit()
         event.accept()
     def newMessage(self, handle, msg):
         if handle in self.config.getBlocklist():
@@ -1625,6 +1626,7 @@ class PesterWindow(MovingWindow):
     joinChannel = QtCore.pyqtSignal(QtCore.QString)
     leftChannel = QtCore.pyqtSignal(QtCore.QString)
     setChannelMode = QtCore.pyqtSignal(QtCore.QString, QtCore.QString, QtCore.QString)
+    closeSignal = QtCore.pyqtSignal()
 
 class IRCThread(QtCore.QThread):
     def __init__(self, ircobj):
@@ -1652,6 +1654,9 @@ class PesterTray(QtGui.QSystemTrayIcon):
             self.setIcon(PesterIcon(self.mainwindow.theme["main/icon"]))
         else:
             self.setIcon(PesterIcon(self.mainwindow.theme["main/newmsgicon"]))
+    @QtCore.pyqtSlot()
+    def mainWindowClosed(self):
+        self.hide()
 
 class MainProgram(QtCore.QObject):
     def __init__(self):
@@ -1698,6 +1703,10 @@ class MainProgram(QtCore.QObject):
                               QtCore.SIGNAL('closeToTraySignal()'),
                               self.trayicon,
                               QtCore.SLOT('show()'))
+        self.trayicon.connect(self.widget,
+                              QtCore.SIGNAL('closeSignal()'),
+                              self.trayicon,
+                              QtCore.SLOT('mainWindowClosed()'))
 
         self.irc = PesterIRC(self.widget)
         self.connectWidgets(self.irc, self.widget)
@@ -1829,7 +1838,7 @@ class MainProgram(QtCore.QObject):
         status = self.widget.loadingscreen.exec_()
         if status == QtGui.QDialog.Rejected:
             sys.exit(0)
-        os._exit(self.app.exec_())
+        sys.exit(self.app.exec_())
 
 pesterchum = MainProgram()
 pesterchum.run()