diff --git a/mutalyzer/Crossmap.py b/mutalyzer/Crossmap.py
index a78a3f2530c659688505d1e4711d895a7f88f54d..cd289e3ebd5e558886bc1204401f4e81cb759847 100644
--- a/mutalyzer/Crossmap.py
+++ b/mutalyzer/Crossmap.py
@@ -435,7 +435,7 @@ class Crossmap() :
         return int(s)
     #main2int
 
-    def int2offset(self, t) :
+    def int2offset(self, t, fuzzy=False):
         """
         Convert a tuple of integers to offset-notation. This adds a `+',
         and `u' or `d' to the offset when appropriate. The main value is
@@ -443,17 +443,22 @@ class Crossmap() :
 
         @arg t: A tuple of integers: (main, offset) in __STOP notation
         @type t: tuple
+        @kwarg fuzzy: Denotes that the coordinate is fuzzy (i.e. offset is
+            unknown).
+        @type fuzzy: bool
 
         @return: The offset in HGVS notation
         @rtype: string
         """
 
         if t[1] > 0 :                      # The exon boundary is downstream.
+            if fuzzy: return '+?'
             if t[0] >= self.__trans_end :  # It is downstream of the last exon.
                 return "+d" + str(t[1])
             return '+' + str(t[1])
         #if
         if t[1] < 0 :                       # The exon boundary is uptream.
+            if fuzzy: return '-?'
             if t[0] <= self.__trans_start : # It is upstream of the first exon.
                 return "-u" + str(-t[1])
             return str(t[1])
@@ -490,32 +495,38 @@ class Crossmap() :
         return int(s[1:])
     #offset2int
 
-    def tuple2string(self, t) :
+    def tuple2string(self, t, fuzzy=False) :
         """
         Convert a tuple (main, offset) in __STOP notation to I{c.} notation.
 
         @arg t: A tuple (main, offset) in __STOP notation
         @type t: tuple
+        @kwarg fuzzy: Denotes that the coordinate is fuzzy (i.e. offset is
+            unknown).
+        @type fuzzy: bool
 
         @return: The position in HGVS notation
         @rtype: string
         """
 
-        return str(self.int2main(t[0])) + str(self.int2offset(t))
+        return str(self.int2main(t[0])) + str(self.int2offset(t, fuzzy))
     #tuple2string
 
-    def g2c(self, a) :
+    def g2c(self, a, fuzzy=False) :
         """
         Uses both g2x() and tuple2string() to translate a genomic position
         to __STOP notation to I{c.} notation.
 
         @arg a: The genomic position that must be translated
         @type a: integer
+        @kwarg fuzzy: Denotes that the coordinate is fuzzy (i.e. offset is
+            unknown).
+        @type fuzzy: bool
 
         @return: The position in HGVS notation
         @rtype: string
         """
-        return self.tuple2string(self.g2x(a))
+        return self.tuple2string(self.g2x(a), fuzzy)
     #g2c
 
     def info(self) :
diff --git a/mutalyzer/GenRecord.py b/mutalyzer/GenRecord.py
index 4f3b1559822cdbf3292fe825cb4b94e865111dc0..3c96487220f582f3f076ed45151dda011194faf4 100644
--- a/mutalyzer/GenRecord.py
+++ b/mutalyzer/GenRecord.py
@@ -81,7 +81,7 @@ class Locus(object) :
             - exon     ; A position list object.
             - txTable  ; The translation table.
             - CM       ; A Crossmap object.
-            
+
         @arg name: identifier of the locus
         @type name: string
         """
@@ -110,21 +110,37 @@ class Locus(object) :
         self.proteinProduct = None
     #__init__
 
-    def addToDescription(self, rawVariant) :
+    def cancelDescription(self):
+        """
+        Set the description on this locus to 'unknown'.
+
+        This can be used if at some point we give up creating a sensible
+        description on this locus. It also makes sure future additions to
+        the description are ignored and it keeps the 'unknown' value.
+
+        @note: This depends on the check for the unknown value in the
+            addToDescription method. This is a not a beatiful solution.
+        """
+        self.description = '?'
+    #cancelDescription
+
+    def addToDescription(self, rawVariant):
         """
         Expands the DNA description with a new raw variant.
-        
+
         @arg rawVariant: description of a single mutation
         @type rawVariant: string
         """
-
         if self.description:
-            self.description = "%s;%s" % (self.description, rawVariant)
-        else :
+            # Don't change anything if we already have an unknown value.
+            if self.description != '?':
+                self.description = "%s;%s" % (self.description, rawVariant)
+        else:
             self.description = rawVariant
     #addToDescription
 #Locus
 
+
 class Gene(object) :
     """
     A Gene object, to store a list of Locus objects and the orientation of
@@ -150,7 +166,7 @@ class Gene(object) :
             - longName ;
         Private variables (altered):
             - __locusTag ;
-            
+
         @arg name: gene name
         @type name: string
         """
@@ -166,7 +182,7 @@ class Gene(object) :
     def newLocusTag(self) :
         """
         Generates a new Locus tag.
-        
+
         @return: Locus tag
         @rtype: integer (3 digits, if < 100 preceeded with 0's)
         """
@@ -179,10 +195,10 @@ class Gene(object) :
     def findLocus(self, name) :
         """
         Find a transcript, given its name.
-        
+
         @arg name: transcript variant number
         @type name: string
-        
+
         @return: transcript
         @rtype: object
         """
@@ -196,7 +212,7 @@ class Gene(object) :
     def listLoci(self) :
         """
         Provides a list of transcript variant numbers
-        
+
         @return: list of transcript variant numbers
         @rtype: list
         """
@@ -210,10 +226,10 @@ class Gene(object) :
     def findLink(self, protAcc) :
         """
         Look in the list of transcripts for a given protein accession number.
-        
+
         @arg protAcc: protein accession number
         @type protAcc: string
-        
+
         @return: transcript
         @rtype: object
         """
@@ -280,10 +296,10 @@ class Record(object) :
     def findGene(self, name) :
         """
         Returns a Gene object, given its name.
-        
+
         @arg name: Gene name
         @type name: string
-        
+
         @return: Gene object
         @rtype: object
         """
@@ -297,10 +313,10 @@ class Record(object) :
     def listGenes(self) :
         """
         List the names of all genes found in this record.
-        
+
         @return: Genes list
         @rtype: list
-        
+
         """
 
         ret = []
@@ -312,7 +328,7 @@ class Record(object) :
     def addToDescription(self, rawVariant) :
         """
         Expands the DNA description with a new raw variant.
-        
+
         @arg rawVariant: description of a single mutation
         @type rawVariant: string
         """
@@ -326,11 +342,11 @@ class Record(object) :
     def toChromPos(self, i) :
         """
         Converts a g. position (relative to the start of the record) to a
-        chromosomal g. position 
-        
+        chromosomal g. position
+
         @arg i: g. position (relative to the start of the record)
         @type i: integer
-        
+
         @return: chromosomal g. position
         @rtype: integer
         """
@@ -366,10 +382,10 @@ class GenRecord() :
     def __init__(self, output, config) :
         """
         Initialise the class.
-        
+
         Public variable:
             - record    ; A record object
-        
+
         @arg output: an output object
         @type output: object
         @arg config: a config object
@@ -384,13 +400,13 @@ class GenRecord() :
     def __checkExonList(self, exonList, CDSpos) :
         """
         @todo document me
-        
+
         @arg exonList: list of splice sites
         @type exonList: list (object)
         @arg CDSpos: location of the CDS
         @type CDSpos: object
-        
-        @return: 
+
+        @return:
         @rtype: boolean
         """
 
@@ -414,12 +430,12 @@ class GenRecord() :
             return True
         return False
     #__checkExonList
-            
+
     def __constructCDS(self, mRNA, CDSpos) :
         """
-        Construct a list of coordinates that contains CDS start and stop and 
+        Construct a list of coordinates that contains CDS start and stop and
         the internal splice sites.
-        
+
         @arg mRNA: mRNA positions/coordinates list
         @type mRNA: list (integer)
         @arg CDSpos: coding DNA positions/coordinates
@@ -449,14 +465,14 @@ class GenRecord() :
         """
         Return the reverse-complement of a DNA sequence if the gene is in
         the reverse orientation.
-        
-        @arg gene: Gene 
+
+        @arg gene: Gene
         @type gene: object
         @arg string: DNA sequence
         @type string: string
         @kwarg string_reverse: DNA sequence to use (if not None) for the
             reverse complement.
-        
+
         @return: reverse-complement (if applicable), otherwise return the
             original.
         @rtype: string
@@ -472,7 +488,7 @@ class GenRecord() :
         """
         Check if the record in self.record is compatible with mutalyzer.
         Update the mRNA PList with the exon and CDS data.
-        
+
         @todo: This function should really check the record for minimal
         requirements
         """
@@ -602,7 +618,8 @@ class GenRecord() :
         return None
     #current_transcript
 
-    def name(self, start_g, stop_g, varType, arg1, arg2, roll, arg1_reverse=None):
+    def name(self, start_g, stop_g, varType, arg1, arg2, roll, arg1_reverse=None,
+             start_fuzzy=False, stop_fuzzy=False):
         """
         Generate variant descriptions for all genes, transcripts, etc.
 
@@ -620,6 +637,10 @@ class GenRecord() :
         @type roll: tuple (integer, integer)
         @kwarg arg1_reverse: argument 1 to be used on reverse strand
         @type arg1_reverse: string
+        @kwarg start_fuzzy: Indicates if start position of variant is fuzzy.
+        @type start_fuzzy: bool
+        @kwarg stop_fuzzy: Indicates if stop position of variant is fuzzy.
+        @type stop_fuzzy: bool
         """
         forwardStart = start_g
         forwardStop = stop_g
@@ -634,23 +655,64 @@ class GenRecord() :
 
         if varType != "subst" :
             if forwardStart != forwardStop :
-                self.record.addToDescription("%s_%s%s%s" % (forwardStart,
-                    forwardStop, varType, arg1))
-                self.record.addToChromDescription("%s_%s%s%s" % (
-                    self.record.toChromPos(forwardStart),
-                    self.record.toChromPos(forwardStop), varType, arg1))
+                # Todo: Fuzzy offsets to genomic positions (see bug #38).
+                #
+                # The genomic positioning is problematic. We would like to
+                # have it in brackets (as fuzzy positions), like the above
+                # g.(34299_23232)del example.
+                #
+                # Now consider a variant c.a-?_b+18del where only the offset
+                # before the exon is unknown but the offset after the exon is
+                # exact. Now a genomic description like g.(34299)_23232del
+                # comes to mind, however, this notation is not allowed by the
+                # HGVS grammar.
+                #
+                # I think all we can do is to treat both positions as fuzzy in
+                # the genomic description, even if only one of them really is.
+                #
+                # Peter thinks the HGVS grammar should at some point be
+                # updated to allow the brackets around individual locations.
+                if start_fuzzy or stop_fuzzy:
+                    self.record.addToDescription("(%s_%s)%s%s" % (
+                        forwardStart, forwardStop, varType, arg1))
+                    self.record.addToChromDescription("(%s_%s)%s%s" % (
+                        self.record.toChromPos(forwardStart),
+                        self.record.toChromPos(forwardStop), varType, arg1))
+                else:
+                    self.record.addToDescription("%s_%s%s%s" % (
+                        forwardStart, forwardStop, varType, arg1))
+                    self.record.addToChromDescription("%s_%s%s%s" % (
+                        self.record.toChromPos(forwardStart),
+                        self.record.toChromPos(forwardStop), varType, arg1))
             #if
             else :
-                self.record.addToDescription("%s%s%s" % (forwardStart, varType,
-                                                         arg1))
-                self.record.addToChromDescription("%s%s%s" % (
-                    self.record.toChromPos(forwardStart), varType, arg1))
+                if start_fuzzy or stop_fuzzy:
+                    # Todo: Current HGVS does not allow for () around single
+                    # positions, only around ranges (see above and #38).
+                    self.record.addToDescription("(%s)%s%s" % (
+                        forwardStart, varType, arg1))
+                    self.record.addToChromDescription("(%s)%s%s" % (
+                        self.record.toChromPos(forwardStart), varType, arg1))
+                else:
+                    self.record.addToDescription("%s%s%s" % (
+                        forwardStart, varType, arg1))
+                    self.record.addToChromDescription("%s%s%s" % (
+                        self.record.toChromPos(forwardStart), varType, arg1))
             #else
         #if
         else :
-            self.record.addToDescription("%s%c>%c" % (forwardStart, arg1, arg2))
-            self.record.addToChromDescription("%s%c>%c" % (
-                self.record.toChromPos(forwardStart), arg1, arg2))
+            if start_fuzzy or stop_fuzzy:
+                # Todo: Current HGVS does not allow for () around single
+                # positions, only around ranges (see above and #38).
+                self.record.addToDescription("(%s)%c>%c" % (
+                    forwardStart, arg1, arg2))
+                self.record.addToChromDescription("(%s)%c>%c" % (
+                    self.record.toChromPos(forwardStart), arg1, arg2))
+            else:
+                self.record.addToDescription("%s%c>%c" % (
+                    forwardStart, arg1, arg2))
+                self.record.addToChromDescription("%s%c>%c" % (
+                    self.record.toChromPos(forwardStart), arg1, arg2))
 
         for i in self.record.geneList :
             for j in i.transcriptList :
@@ -683,24 +745,45 @@ class GenRecord() :
 
                     if varType != "subst" :
                         if orientedStart != orientedStop :
-                            j.addToDescription("%s_%s%s%s" % (
-                                j.CM.g2c(orientedStart), j.CM.g2c(orientedStop),
-                                varType, self.__maybeInvert(i, arg1, arg1_reverse)))
-                            self.checkIntron(i, j, orientedStart)
-                            self.checkIntron(i, j, orientedStop)
+                            if (start_fuzzy or stop_fuzzy) and not j.current:
+                                # Don't generate descriptions on transcripts
+                                # other than the current in the case of fuzzy
+                                # positions.
+                                j.cancelDescription()
+                            else:
+                                j.addToDescription("%s_%s%s%s" % (
+                                    j.CM.g2c(orientedStart, start_fuzzy),
+                                    j.CM.g2c(orientedStop, stop_fuzzy),
+                                    varType, self.__maybeInvert(i, arg1, arg1_reverse)))
+                                self.checkIntron(i, j, orientedStart)
+                                self.checkIntron(i, j, orientedStop)
                         #if
                         else :
-                            j.addToDescription("%s%s%s" % (
-                                j.CM.g2c(orientedStart), varType,
-                                self.__maybeInvert(i, arg1, arg1_reverse)))
-                            self.checkIntron(i, j, orientedStart)
+                            if start_fuzzy and not j.current:
+                                # Don't generate descriptions on transcripts
+                                # other than the current in the case of fuzzy
+                                # positions.
+                                j.cancelDescription()
+                            else:
+                                j.addToDescription("%s%s%s" % (
+                                    j.CM.g2c(orientedStart, start_fuzzy),
+                                    varType,
+                                    self.__maybeInvert(i, arg1, arg1_reverse)))
+                                self.checkIntron(i, j, orientedStart)
                         #else
                     #if
                     else :
-                        j.addToDescription("%s%c>%c" % (j.CM.g2c(orientedStart),
-                            self.__maybeInvert(i, arg1, arg1_reverse),
-                            self.__maybeInvert(i, arg2)))
-                        self.checkIntron(i, j, orientedStart)
+                        if start_fuzzy and not j.current:
+                            # Don't generate descriptions on transcripts
+                            # other than the current in the case of fuzzy
+                            # positions.
+                            j.cancelDescription()
+                        else:
+                            j.addToDescription("%s%c>%c" % (
+                                j.CM.g2c(orientedStart, start_fuzzy),
+                                self.__maybeInvert(i, arg1, arg1_reverse),
+                                self.__maybeInvert(i, arg2)))
+                            self.checkIntron(i, j, orientedStart)
                     #else
                 #if
             #for
@@ -710,14 +793,14 @@ class GenRecord() :
     def checkIntron(self, gene, transcript, position) :
         """
         Checks if a position is on or near a splice site
-        
+
         @arg gene: Gene
         @type gene: object
         @arg transcript: transcript
         @type transcript: object
         @arg position: g. position
         @type position: integer
-        
+
         @return:
         @todo: Also check a range properly.
         """
diff --git a/mutalyzer/templates/check.html b/mutalyzer/templates/check.html
index 271293e2bff8feb9fa951c69f396e97ee5e51958..ca1fd558341c2202182036351688ad0a207221c9 100644
--- a/mutalyzer/templates/check.html
+++ b/mutalyzer/templates/check.html
@@ -95,9 +95,10 @@
           <b>Affected transcripts:</b><br>
           <br>
           <tt tal:repeat = "i descriptions">
-            <a tal:content = "i/0"
+            <a tal:condition = "i/1" tal:content = "i/0"
                tal:attributes = 
-                 "href string:checkForward?mutationName=${i/1}"></a><br>
+                 "href string:checkForward?mutationName=${i/1}"></a><tal
+               tal:condition = "not:i/1" tal:replace = "i/0"></tal><br> 
           </tt>
           <br>
           <br>
diff --git a/mutalyzer/variantchecker.py b/mutalyzer/variantchecker.py
index 4068cba0424ad8aa16e241d76a88c941d72e71dc..126219694ceac857f7c2b6e21994fbac27b45e30 100644
--- a/mutalyzer/variantchecker.py
+++ b/mutalyzer/variantchecker.py
@@ -302,7 +302,8 @@ def apply_substitution(position, original, substitute, mutator, record, O):
 #apply_substitution
 
 
-def apply_deletion_duplication(first, last, type, mutator, record, O):
+def apply_deletion_duplication(first, last, type, mutator, record, O,
+                               first_fuzzy=False, last_fuzzy=False):
     """
     Do a semantic check for a deletion or duplication, do the actual
     deletion/duplication and give it a name.
@@ -319,6 +320,13 @@ def apply_deletion_duplication(first, last, type, mutator, record, O):
     @type record: Modules.GenRecord.GenRecord
     @arg O: The Output object.
     @type O: Modules.Output.Output
+
+    @kwarg first_fuzzy: Denotes that the start position is fuzzy (e.g. in the
+        case of an unknown offset in c. notation).
+    @type first_fuzzy: bool
+    @kwarg last_fuzzy: Denotes that the end position is fuzzy (e.g. in the
+        case of an unknown offset in c. notation).
+    @type last_fuzzy: bool
     """
     reverse_roll, forward_roll = util.roll(mutator.orig, first, last)
 
@@ -391,7 +399,9 @@ def apply_deletion_duplication(first, last, type, mutator, record, O):
     else:
         mutator.dupM(first, last)
 
-    record.name(first, last, type, '', '', (reverse_roll, forward_roll))
+    record.name(first, last, type, '', '', (reverse_roll, forward_roll),
+                start_fuzzy=first_fuzzy,
+                stop_fuzzy=last_fuzzy)
 #apply_deletion_duplication
 
 
@@ -644,21 +654,71 @@ def apply_delins(first, last, delete, insert, mutator, record, output):
 #apply_delins
 
 
-def _get_offset(location):
+def _get_offset(location, main_genomic, sites, output):
     """
     Convert the offset coordinate in a location (from the Parser) to an
     integer.
 
     @arg location: A location.
     @type location: pyparsing.ParseResults
+    @arg main_genomic: Genomic main position to which the offset belongs.
+    @type main_genomic: int
+    @arg sites: List of splice sites.
+    @type sites: list
+    @arg output: The Output object.
+    @type output: Modules.Output.Output
 
     @return: Integer representation of the offset coordinate.
     @rtype: int
     """
     if location.Offset :
-        if location.Offset == '?' : # This is highly debatable.
-            return 0
-        offset = int(location.Offset)
+        if location.Offset == '?' :
+            try:
+                # Todo: If it removes CDS start, don't do protein translation.
+                # Todo: Wrt orientation, perhaps always go to splice site
+                #     locations via the crossmapper...
+                # Todo: Also check if +? and -? are correctly used.
+                # Todo: Exactly centering might not be so nice, since the center
+                # might be closer to a neighbouring exon, making a+xxx from b-?
+                # and vice versa. This might not be fixed directly by doing a
+                # center +/- 1 because there might be rolling. Ideally we
+                # disable rolling entirely for these positions...
+                #
+                # Note that the code below might be a bit confusing, especially
+                # considering reverse strand transcripts. Magically, it works
+                # for both orientations.
+                i = sites.index(main_genomic)
+                if i == 0:
+                    # Before first exon (or last on the reverse strand).
+                    offset = main_genomic / 2
+                elif i == len(sites) - 1:
+                    # After last exon (or first on the reverse strand).
+                    # Todo: Get length of reference, and calculate a sensible
+                    # offset.
+                    #
+                    # We now use that 2000 is the default downstream length,
+                    # but of course this is bogus on the reverse strand and
+                    # just a hack anyway.
+                    offset = 1000
+                elif i % 2 == 0:
+                    # Acceptor site (or donor on the reverse strand).
+                    offset = abs(main_genomic - sites[i - 1]) / 2 - 1
+                else:
+                    # Donor site (or acceptor on the reverse strand).
+                    offset = abs(sites[i + 1] - main_genomic) / 2 - 1
+                # Todo: We would like to use the c. position in this message.
+                output.addMessage(__file__, 1, "IUNKNOWNOFFSET", "Unknown offset " \
+                                  "relative to %s interpreted as middle of " \
+                                  "flanking intron." % main_genomic)
+            except ValueError:
+                # Todo: This means we don't get an error if the main position
+                # was not on an exon boundary. We should return something else
+                # than 0 I guess.
+                #return 0  # This is highly debatable.
+                # Any non-zero value will do.
+                return 1
+        else:
+            offset = int(location.Offset)
         if location.OffSgn == '-' :
             return -offset
         return offset
@@ -761,7 +821,7 @@ def _genomic_to_genomic(first_location, last_location):
     return first, last
 
 
-def _coding_to_genomic(first_location, last_location, transcript):
+def _coding_to_genomic(first_location, last_location, transcript, output):
     """
     Get genomic range from parsed c. location.
 
@@ -771,6 +831,8 @@ def _coding_to_genomic(first_location, last_location, transcript):
     @type last_location: pyparsing.ParseResults
     @arg transcript: todo
     @type transcript: todo
+    @arg output: The Output object.
+    @type output: Modules.Output.Output
 
     @return: A tuple of:
         - first: Genomic start location represented by given location.
@@ -792,11 +854,15 @@ def _coding_to_genomic(first_location, last_location, transcript):
 
     first_main = transcript.CM.main2int(first_location.MainSgn + \
                                         first_location.Main)
-    first_offset = _get_offset(first_location)
+    first_main_genomic = transcript.CM.x2g(first_main, 0)
+    first_offset = _get_offset(first_location, first_main_genomic,
+                               transcript.CM.RNA, output)
 
     last_main = transcript.CM.main2int(last_location.MainSgn + \
                                        last_location.Main)
-    last_offset = _get_offset(last_location)
+    last_main_genomic = transcript.CM.x2g(last_main, 0)
+    last_offset = _get_offset(last_location, last_main_genomic,
+                              transcript.CM.RNA, output)
 
     # These raise _RawVariantError exceptions on invalid positions.
     _check_intronic_position(first_main, first_offset, transcript)
@@ -912,7 +978,8 @@ def process_raw_variant(mutator, variant, record, transcript, output):
         try:
             if transcript:
                 # Coding positioning.
-                first, last = _coding_to_genomic(first_location, last_location, transcript)
+                first, last = _coding_to_genomic(first_location, last_location,
+                                                 transcript, output)
             else:
                 # Genomic positioning.
                 first, last = _genomic_to_genomic(first_location, last_location)
@@ -1062,8 +1129,12 @@ def process_raw_variant(mutator, variant, record, transcript, output):
 
     # Deletion or duplication.
     if variant.MutationType in ['del', 'dup']:
+        # The fuzzy flags are to support deletions of the form c.a-?_b+?del.
+        first_fuzzy = variant.StartLoc.PtLoc.Offset == '?'
+        last_fuzzy = variant.EndLoc and variant.EndLoc.PtLoc.Offset == '?'
         apply_deletion_duplication(first, last, variant.MutationType, mutator,
-                                   record, output)
+                                   record, output, first_fuzzy=first_fuzzy,
+                                   last_fuzzy=last_fuzzy)
 
     # Inversion.
     if variant.MutationType == 'inv':
@@ -1259,6 +1330,9 @@ def process_variant(mutator, description, record, output):
             if transcript_id:
                 transcript = gene.findLocus(transcript_id)
                 if not transcript:
+                    # Todo: Incorrect error message, it might also be that
+                    # there are no transcripts at all (e.g. N4BP2L1 on
+                    # NG_012772.1).
                     output.addMessage(__file__, 4, "ENOTRANSCRIPT",
                         "Multiple transcripts found for gene %s. Please " \
                         "choose from: %s" %(gene.name,
@@ -1302,6 +1376,9 @@ def process_variant(mutator, description, record, output):
                     # this gene.
                     transcript = gene.transcriptList[0]
                 else:
+                    # Todo: Incorrect error message, it might also be that
+                    # there are no transcripts at all (e.g. N4BP2L1 on
+                    # NG_012772.1).
                     output.addMessage(__file__, 4, "ENOTRANSCRIPT",
                         "Multiple transcripts found for gene %s. Please " \
                         "choose from: %s" %(gene.name,
@@ -1484,6 +1561,7 @@ def check_variant(description, config, output):
                                             mutator.newSplice(transcript.CDS.positionList),
                                             transcript.CM.orientation)),
                               IUPAC.unambiguous_dna)
+
             if transcript.CM.orientation == -1:
                 cds_original = Bio.Seq.reverse_complement(cds_original)
                 cds_variant = Bio.Seq.reverse_complement(cds_variant)
@@ -1509,9 +1587,15 @@ def check_variant(description, config, output):
                     return
                 protein_variant = cds_variant.translate(table=transcript.txTable,
                                                         to_stop=True)
-                cds_length = util.cds_length(mutator.newSplice(transcript.CDS.positionList))
-                transcript.proteinDescription = util.protein_description(
-                    cds_length, protein_original, protein_variant)[0]
+                try:
+                    cds_length = util.cds_length(
+                        mutator.newSplice(transcript.CDS.positionList))
+                    transcript.proteinDescription = util.protein_description(
+                        cds_length, protein_original, protein_variant)[0]
+                except IndexError:
+                    # Todo: Probably CDS start was hit by removal of exon...
+                    transcript.proteinDescription = 'p.?'
+
             else:
                 output.addMessage(__file__, 2, "ECDS", "CDS length is " \
                     "not a multiple of three in gene %s, transcript " \
diff --git a/mutalyzer/website.py b/mutalyzer/website.py
index 817bb0e35724299eb0b0d75add0bfee89323ef5b..be9c833b4362d8716ee0a53344e2cd02b5473e90 100644
--- a/mutalyzer/website.py
+++ b/mutalyzer/website.py
@@ -685,6 +685,13 @@ class Check:
 
         genomic_description = output.getIndexedOutput('genomicDescription', 0, '')
 
+        # Create a tuple (description, link) from a description
+        def description_to_link(description):
+            link = None
+            if description[-1] != '?':
+                link = urllib.quote(description)
+            return description, link
+
         # Todo: Generate the fancy HTML views for the proteins here instead
         # of in mutalyzer/variantchecker.py.
         args = {
@@ -697,7 +704,7 @@ class Check:
             'chromDescription'   : output.getIndexedOutput('genomicChromDescription', 0),
             'genomicDNA'         : genomic_dna,
             'visualisation'      : output.getOutput('visualisation'),
-            'descriptions'       : map(lambda d: (d, urllib.quote(d)), output.getOutput('descriptions')),
+            'descriptions'       : map(description_to_link, output.getOutput('descriptions')),
             'protDescriptions'   : output.getOutput('protDescriptions'),
             'oldProtein'         : output.getOutput('oldProteinFancy'),
             'altStart'           : output.getIndexedOutput('altStart', 0),
diff --git a/tests/test_variantchecker.py b/tests/test_variantchecker.py
index be4c39bf5e585aa445850091e5f7e2cd5ba84dba..debc39bfdd49999a817e8668cf79e3e7634912de 100644
--- a/tests/test_variantchecker.py
+++ b/tests/test_variantchecker.py
@@ -262,7 +262,6 @@ class TestVariantchecker():
         """
         Deletion of an entire exon with unknown offsets should be possible.
         """
-        return # Todo
         check_variant('NG_012772.1(BRCA2_v001):c.632-?_681+?del',
                       self.config, self.output)
         assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0
@@ -275,6 +274,8 @@ class TestVariantchecker():
                      'NG_012772.1:g.(17550_19725)del')
         assert 'NG_012772.1(BRCA2_v001):c.632-?_681+?del' \
                in self.output.getOutput('descriptions')
+        assert 'NG_012772.1(BRCA2_i001):p.(Val211Glufs*10)' \
+               in self.output.getOutput('protDescriptions')
         # Todo: .c notation should still be c.632-?_681+?del, but what about
         # other transcripts?
 
@@ -287,7 +288,6 @@ class TestVariantchecker():
         NG_012772.1(BRCA2_v001):c.68-?_316+?del is such a variant, since
         positions 68 through 316 are exactly one exon and (316-68+1)/3 = 83.
         """
-        return # Todo
         check_variant('NG_012772.1(BRCA2_v001):c.68-?_316+?del',
                       self.config, self.output)
         assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0
@@ -308,8 +308,7 @@ class TestVariantchecker():
         Deletion of an entire exon with unknown offsets and another composed
         variant with exact positioning should be possible.
         """
-        return # Todo
-        check_variant('UD_129433404385(DMD_v010):c.[281-?_492+?del;492+4del]',
+        check_variant('NG_012772.1(BRCA2_v001):c.[632-?_681+?del;681+4del]',
                       self.config, self.output)
         assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0
         assert len(self.output.getMessagesWithErrorCode('IDELSPLICE')) > 0
@@ -318,8 +317,28 @@ class TestVariantchecker():
         assert self.output.getOutput('newprotein')
         # Genomic positions should be centered in flanking introns and unsure.
         assert_equal(self.output.getIndexedOutput('genomicDescription', 0),
-                     'UD_129433404385:g.[(1640003_1675849)del;1665239del]')
-        assert 'UD_129433404385(DMD_v010):c.[281-?_492+?del;492+4del]' \
+                     'NG_012772.1:g.[(17550_19725)del;19017del]')
+        assert 'NG_012772.1(BRCA2_v001):c.[632-?_681+?del;681+4del]' \
+               in self.output.getOutput('descriptions')
+        # Todo: .c notation should still be c.632-?_681+?del, but what about
+        # other transcripts?
+
+    def test_del_exon_unknown_offsets_reverse(self):
+        """
+        Deletion of an entire exon with unknown offsets should be possible,
+        also on the reverse strand.
+        """
+        check_variant('AL449423.14(CDKN2A_v001):c.151-?_457+?del',
+                      self.config, self.output)
+        assert len(self.output.getMessagesWithErrorCode('WOVERSPLICE')) > 0
+        assert len(self.output.getMessagesWithErrorCode('IDELSPLICE')) > 0
+        # Todo: For now, the following is how to check if protein
+        # prediction is done.
+        assert self.output.getOutput('newprotein')
+        # Genomic positions should be centered in flanking introns and unsure.
+        assert_equal(self.output.getIndexedOutput('genomicDescription', 0),
+                     'AL449423.14:g.(60314_63683)del')
+        assert 'AL449423.14(CDKN2A_v001):c.151-?_457+?del' \
                in self.output.getOutput('descriptions')
         # Todo: .c notation should still be c.632-?_681+?del, but what about
         # other transcripts?
diff --git a/tests/test_website.py b/tests/test_website.py
index de31f2c74cd84992b8046aafc15f0734263683f3..089e09a97cbdf1a27dd663921458c1b0d7e9ef15 100644
--- a/tests/test_website.py
+++ b/tests/test_website.py
@@ -577,7 +577,6 @@ facilisi."""
             and thus the cached file from request i cannot be re-used in
             request i+1.
         """
-        return
         r = self.app.get('/check')
         form = r.forms[0]
         form['mutationName'] = 'AB026906.1:c.274G>T'