@@ -6963,6 +6963,60 @@ bool MCStringGetNumericValue(MCStringRef self, double &r_value)
69636963 return false ;
69646964}
69656965
6966+ MC_DLLEXPORT
6967+ bool MCStringNormalizeLineEndings (MCStringRef p_input,
6968+ MCStringLineEndingStyle p_to_style,
6969+ MCStringRef& r_output,
6970+ MCStringLineEndingStyle* r_original_style)
6971+ {
6972+ uindex_t t_firstLF = 0 ;
6973+ uindex_t t_firstCR = 0 ;
6974+ MCStringLineEndingStyle t_original_style = kMCStringLineEndingStyleLF ;
6975+ MCStringRef t_mutable_input;
6976+
6977+ if (MCStringFirstIndexOfChar (p_input, ' \r ' , 0 , kMCStringOptionCompareExact , t_firstCR))
6978+ {
6979+ if (MCStringFirstIndexOfChar (p_input, ' \n ' , 0 , kMCStringOptionCompareExact , t_firstLF))
6980+ {
6981+ if ((t_firstCR + 1 == t_firstLF) || (t_firstLF + 1 == t_firstCR))
6982+ t_original_style = kMCStringLineEndingStyleCRLF ;
6983+ else if (t_firstCR < t_firstLF)
6984+ t_original_style = kMCStringLineEndingStyleCR ;
6985+ }
6986+ else
6987+ t_original_style = kMCStringLineEndingStyleCR ;
6988+ }
6989+
6990+ // normalize input to LF line endings first
6991+ /* UNCHECKED */ MCStringMutableCopy (p_input, t_mutable_input);
6992+ /* UNCHECKED */ MCStringFindAndReplace (t_mutable_input, MCSTR (" \r\n " ),
6993+ MCSTR (" \n\r " ), kMCStringOptionCompareExact );
6994+ /* UNCHECKED */ MCStringFindAndReplace (t_mutable_input, MCSTR (" \n\r " ),
6995+ MCSTR (" \n " ), kMCStringOptionCompareExact );
6996+ /* UNCHECKED */ MCStringFindAndReplace (t_mutable_input, MCSTR (" \r " ),
6997+ MCSTR (" \n " ), kMCStringOptionCompareExact );
6998+
6999+ // AL-2014-07-21: [[ Bug 12162 ]] Convert PS to LF, and LS to VT on text import.
7000+ /* UNCHECKED */ MCStringFindAndReplaceChar (t_mutable_input,
7001+ (const codepoint_t )0x2028 , (const codepoint_t )0x0B ,
7002+ kMCStringOptionCompareExact );
7003+ /* UNCHECKED */ MCStringFindAndReplaceChar (t_mutable_input,
7004+ (const codepoint_t )0x2029 , (const codepoint_t )0x0A ,
7005+ kMCStringOptionCompareExact );
7006+
7007+ // now convert the line endings to the proper version
7008+ if (p_to_style == kMCStringLineEndingStyleCR )
7009+ /* UNCHECKED */ MCStringFindAndReplace (t_mutable_input, MCSTR (" \n " ),
7010+ MCSTR (" \r " ), kMCStringOptionCompareExact );
7011+ else if (p_to_style == kMCStringLineEndingStyleCRLF )
7012+ /* UNCHECKED */ MCStringFindAndReplace (t_mutable_input, MCSTR (" \n " ),
7013+ MCSTR (" \r\n " ), kMCStringOptionCompareExact );
7014+
7015+ if (r_original_style != nullptr ) *r_original_style = t_original_style;
7016+ /* UNCHECKED */ MCStringCopyAndRelease (t_mutable_input, r_output);
7017+ return true ;
7018+ }
7019+
69667020static void __MCStringCheck (MCStringRef self)
69677021{
69687022 __MCAssertIsString (self);
0 commit comments