--- ./app_voicemail.c.orig	2004-01-12 18:35:45.000000000 -0600
+++ ./app_voicemail.c	2004-01-13 20:03:23.000000000 -0600
@@ -194,6 +194,8 @@
 static char fromstring[100];
 static char emailtitle[100];
 
+static char cancelkey;
+
 STANDARD_LOCAL_USER;
 
 LOCAL_USER_DECL;
@@ -1239,7 +1241,15 @@
 					outmsg = 2;
 					ast_frfree(f);
 					break;
-				}
+
+ 				} else if (f->subclass == cancelkey) {
+ 					if (option_verbose > 2) 
+ 						ast_verbose( VERBOSE_PREFIX_3 "User canceled message by pressing %c\n", f->subclass);
+ 					res = cancelkey;
+ 					outmsg = 0;
+ 					ast_frfree(f);
+ 					break;     
+            }       
 			}
 			if (maxtime) {
 				time(&end);
@@ -1314,13 +1324,18 @@
 	char prefile[256]="";
 	char fmt[80];
 	char *context;
-	char *ecodes = "#";
+	char ecodes[256] = "#";
 	char *stringp;
 	time_t start;
 	time_t end;
 	char tmp[256] = "";
 	struct ast_vm_user *vmu;
 	struct ast_vm_user svm;
+
+ 	char *pfmt = NULL;
+ 	int x;
+ 	int fmtcnt=1;
+ 	char *sfmt[MAX_OTHER_FORMATS];
 	
 	strncpy(tmp, ext, sizeof(tmp) - 1);
 	ext = tmp;
@@ -1348,12 +1363,15 @@
 		if (mkdir(dir, 0700) && (errno != EEXIST))
 			ast_log(LOG_WARNING, "mkdir '%s' failed: %s\n", dir, strerror(errno));
 		if (ast_exists_extension(chan, strlen(chan->macrocontext) ? chan->macrocontext : chan->context, "o", 1, chan->callerid))
-			ecodes = "#0";
+			strncpy(ecodes, "#0", sizeof(ecodes)-1);
+
+		if (cancelkey) strncat(ecodes, &cancelkey, sizeof(ecodes)-1);
+
 		/* Play the beginning intro if desired */
 		if (strlen(prefile)) {
 			if (ast_fileexists(prefile, NULL, NULL) > 0) {
-				if (ast_streamfile(chan, prefile, chan->language) > -1) 
-				    res = ast_waitstream(chan, "#0");
+				if (ast_streamfile(chan, prefile, chan->language) > -1)  
+				    res = ast_waitstream(chan, ecodes); 
 			} else {
 				ast_log(LOG_DEBUG, "%s doesn't exist, doing what we can\n", prefile);
 				res = invent_message(chan, vmu->context, ext, busy, ecodes);
@@ -1368,7 +1386,15 @@
 			/* On a '#' we skip the instructions */
 			silent = 1;
 			res = 0;
+
+		} else if (res == cancelkey) {
+	                if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid)) { 
+				chan->priority+=50;
+				free_user(vmu);
+				return 0;
+			}
 		}
+
 		if (!res && !silent) {
 			res = ast_streamfile(chan, INTRO, chan->language);
 			if (!res)
@@ -1376,6 +1402,20 @@
 			if (res == '#') {
 				silent = 1;
 				res = 0;
+
+			} else if (res == cancelkey) {
+	                	if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid)) { 
+					chan->priority+=50;
+					free_user(vmu);
+					return 0;
+				}
+			}
+		}
+		if (res == cancelkey) {
+	               	if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid)) { 
+				chan->priority+=50;
+				free_user(vmu);
+				return 0;
 			}
 		}
 		/* Check for a '0' here */
@@ -1411,12 +1451,36 @@
 				msgnum++;
 			} while(msgnum < MAXMSG);
 			if (msgnum < MAXMSG) {
+
+	     		get_date(date, sizeof(date));
+				time(&start);
+   			res = play_and_record(chan, NULL, fn, vmmaxmessage, fmt);                
+
+		        if (res == cancelkey) {
+				stringp=vmfmts;
+				strsep(&stringp, "|");
+        			sfmt[0] = ast_strdupa(vmfmts);
+				while((pfmt = strsep(&stringp, "|"))) {
+					sfmt[fmtcnt++] = ast_strdupa(pfmt);
+				}
+		            	for (x=0;x<fmtcnt;x++) {
+                			ast_verbose( VERBOSE_PREFIX_3 "deleting: %s format: %s\n", fn, sfmt[x]); 
+		            		ast_filedelete(fn, sfmt[x]);  
+		            	}
+            			ast_verbose( VERBOSE_PREFIX_3 "Macro, context (%s, %s)\n", chan->macrocontext, chan->context);
+		                if (ast_exists_extension(chan, chan->context, chan->exten, chan->priority + 51, chan->callerid)) { 
+					chan->priority+=50;
+	            			ast_verbose( VERBOSE_PREFIX_3 "Spawning extension (%s, %s, %d)\n", chan->context, chan->exten, chan->priority);
+				} else {
+	            			ast_verbose( VERBOSE_PREFIX_3 "Extension (%s, %s, %d) does not exist.\n", chan->context, chan->exten, chan->priority+51);
+				}
+  		          	return 0;
+			}         
+         
 				/* Store information */
 				snprintf(txtfile, sizeof(txtfile), "%s.txt", fn);
  				txt = fopen(txtfile, "w+");
 				if (txt) {
-					get_date(date, sizeof(date));
-					time(&start);
 					fprintf(txt, 
 ";\n"
 "; Message Information file\n"
@@ -1440,7 +1504,7 @@
 					fclose(txt);
 				} else
 					ast_log(LOG_WARNING, "Error opening text file for output\n");
-				res = play_and_record(chan, NULL, fn, vmmaxmessage, fmt);
+
 				if (res > 0)
 					res = 0;
 				txt = fopen(txtfile, "a");
@@ -2943,6 +3007,8 @@
 	int res=0, silent=0, busy=0, unavail=0;
 	struct localuser *u;
 	char tmp[256], *ext;
+
+	cancelkey = '\0';
 	
 	LOCAL_USER_ADD(u);
 	if (chan->_state != AST_STATE_UP)
@@ -2967,6 +3033,12 @@
 		} else if (*ext == 'u') {
 			unavail=1;
 			ext++;
+		} else if (*ext == 'c') {
+			ext++;
+			if ( (*ext >= '0' && *ext <= '9' ) || *ext == '*') {
+				cancelkey=*ext;
+				ext++;
+			}
 		} else 
 			break;
 	}
@@ -3178,7 +3250,7 @@
 			if (maxsilence > 0)
 				maxsilence *= 1000;
 		}
-		
+
 		silencethreshold = 256;
 		if ((thresholdstr = ast_variable_retrieve(cfg, "general", "silencethreshold")))
 			silencethreshold = atoi(thresholdstr);
