diff --git a/src/sbbs3/writemsg.cpp b/src/sbbs3/writemsg.cpp
index e740547bf992eefbc5527423e96aba0cd9c5d72d..3013d946a9b30cde7674aaf99a25c47358126aa5 100644
--- a/src/sbbs3/writemsg.cpp
+++ b/src/sbbs3/writemsg.cpp
@@ -931,7 +931,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
 
 	maxlines=cfg.level_linespermsg[useron.level];
 
-	if((str = strListSplit(NULL, buf, "\r\n")) == NULL) {
+	if((str = strListDivide(NULL, buf, "\n")) == NULL) {
 		errormsg(WHERE,ERR_ALLOC,"msgeditor",sizeof(char *)*(maxlines+1));
 		return(0); 
 	}
@@ -939,6 +939,7 @@ ulong sbbs_t::msgeditor(char *buf, const char *top, char *title)
 	while(lines > maxlines)
 		free(str[--lines]);
 	str[lines] = NULL;
+	strListTruncateTrailingLineEndings(str);
 	if(lines)
 		bprintf("\r\nMessage editor: Read in %d lines\r\n",lines);
 	bprintf(text[EnterMsgNow],maxlines);
diff --git a/src/xpdev/str_list.c b/src/xpdev/str_list.c
index aeace2d05c0f3ffb1fb5f62cde5aa5e387c2eba6..f2bd8372844b3c375d9b1ad51fc6ec68d0fd975b 100644
--- a/src/xpdev/str_list.c
+++ b/src/xpdev/str_list.c
@@ -370,6 +370,7 @@ char* strListInsertFormat(str_list_t* list, size_t index, const char* format, ..
 }
 #endif
 
+// Consecutive delimiters are treated as one (empty strings are skipped)
 str_list_t strListSplit(str_list_t* lp, char* str, const char* delimit)
 {
 	size_t	count;
@@ -416,6 +417,38 @@ str_list_t strListSplitCopy(str_list_t* list, const char* str, const char* delim
 	return(new_list);
 }
 
+// Consecutive delimiters are treated as multiple (empty strings are supported)
+str_list_t strListDivide(str_list_t* lp, char* str, const char* delimit)
+{
+	size_t	count;
+	char*	p = str;
+	char*	np;
+	char*	end;
+	str_list_t	list;
+
+	if(str == NULL || delimit == NULL)
+		return NULL;
+
+	if(lp == NULL) {
+		if((list = strListInit()) == NULL)
+			return NULL;
+		lp = &list;
+		count = 0;
+	} else
+		count = strListCount(*lp);
+
+	end = str + strlen(str);
+	while(p < end) {
+		np = p + strcspn(p, delimit);
+		*np = '\0';
+		strListAppend(lp, p, count++);
+		p = np + 1;
+	}
+
+	return *lp;
+}
+
+
 size_t strListMerge(str_list_t* list, str_list_t add_list)
 {
 	size_t	i;
diff --git a/src/xpdev/str_list.h b/src/xpdev/str_list.h
index a5994b359efe7f4c14c6b49ff7b4ab374b864a34..8bc96477af519129e9af89772d1db9e61616722a 100644
--- a/src/xpdev/str_list.h
+++ b/src/xpdev/str_list.h
@@ -100,12 +100,16 @@ DLLEXPORT BOOL			strListSwap(const str_list_t, size_t index1, size_t index2);
 #define		strListPop(list)		strListRemove(list, STR_LIST_LAST_INDEX)
 
 /* Add to an existing or new string list by splitting specified string (str) */
-/* into multiple strings, separated by one of the delimit characters */
+/* into multiple (non-empty) strings, separated by one or more of the delimit characters */
 DLLEXPORT str_list_t	strListSplit(str_list_t*, char* str, const char* delimit);
 
 /* Same as above, but copies str to temporary heap buffer first */
 DLLEXPORT str_list_t	strListSplitCopy(str_list_t*, const char* str, const char* delimit);
 
+/* Add to an existing or new string list by splitting specified string (str) */
+/* into multiple (possibly empty) strings, separated by one of the delimit characters */
+DLLEXPORT str_list_t	strListDivide(str_list_t*, char* str, const char* delimit);
+
 /* Merge 2 string lists (no copying of string data) */
 DLLEXPORT size_t		strListMerge(str_list_t*, str_list_t append_list);