diff --git a/programs/cmm/TWB/TWB.c b/programs/cmm/TWB/TWB.c index b25f7277f..f3928bef3 100644 --- a/programs/cmm/TWB/TWB.c +++ b/programs/cmm/TWB/TWB.c @@ -29,9 +29,8 @@ struct TWebBrowser { void DrawStyle(); void DrawPage(); void DrawScroller(); - void LoadInternalPage(); void NewLine(); - void Perenos(); + bool CheckForLineBreak(); void BufEncode(); } WB1; @@ -97,11 +96,11 @@ void TWebBrowser::DrawStyle() line_length = stolbec_len * list.font_w; if (debug_mode) { - DrawBuf.DrawBar(start_x, draw_y, line_length, list.item_h-1, 0xDDDddd); + DrawBuf.DrawBar(start_x, draw_y, line_length, list.item_h, 0xDDDddd); } if (style.bg_color!=page_bg) { - DrawBuf.DrawBar(start_x, draw_y, line_length, list.item_h-1, style.bg_color); + DrawBuf.DrawBar(start_x, draw_y, line_length, list.item_h, style.bg_color); } if (style.image) { @@ -118,20 +117,16 @@ void TWebBrowser::DrawStyle() if (style.u) DrawBuf.DrawBar(start_x, list.item_h - zoom - zoom + draw_y, line_length, zoom, text_colors[text_color_index]); if (link) { if (line[0]==' ') && (line[1]==NULL) {} else { - DrawBuf.DrawBar(start_x, draw_y + list.item_h - calc(zoom*2), line_length, zoom, text_colors[text_color_index]); + DrawBuf.DrawBar(start_x, draw_y + list.item_h - calc(zoom*2), line_length, zoom, link_color_inactive); PageLinks.AddText(start_x, draw_y + list.y, line_length, list.item_h - calc(zoom*2), UNDERLINE, zoom); } } stolbec += stolbec_len; + if (debug_mode) debug(#line); + line = NULL; } } //============================================================================================ -void TWebBrowser::LoadInternalPage(dword bufpos, in_filesize){ - bufsize = in_filesize; - bufpointer = bufpos; - Prepare(); -} -//============================================================================================ void TWebBrowser::SetPageDefaults() { style.b = style.u = style.s = style.h = style.blq = t_html = t_body = style.pre = @@ -171,7 +166,6 @@ void TWebBrowser::Prepare(){ if (style.pre) { DrawStyle(); - line = NULL; NewLine(); break; } @@ -193,10 +187,11 @@ void TWebBrowser::Prepare(){ } if (bukva = GetUnicodeSymbol(#tag)) { bufpos += j; + CheckForLineBreak(); } else { bukva = '&'; + goto DEFAULT_MARK; } - goto DEFAULT_MARK; break; case '<': bufpos++; @@ -223,6 +218,7 @@ void TWebBrowser::Prepare(){ { ignor_param = true; if (strlen(#tagparam)+1list.column_max) { - perenos_num=list.column_max/zoom; + if (strlen(#line)*zoom + stolbec < list.column_max) return false; + line_break_pos = strrchr(#line, ' '); + if (line_break_pos*zoom + stolbec > list.column_max) { + line_break_pos = list.column_max/zoom - stolbec; + while(line_break_pos) && (line[line_break_pos]!=' ') line_break_pos--; + } + if (!line_break_pos) && (strlen(#line)*zoom>list.column_max) { + line_break_pos=list.column_max/zoom; if (!stolbec)&&(style.pre) draw_y-=list.item_h; //hack to fix https://prnt.sc/rk3kyt } - strcpy(#new_line_text, #line + perenos_num); - line[perenos_num] = 0x00; + strcpy(#new_line_text, #line + line_break_pos); + line[line_break_pos] = 0x00; DrawStyle(); strcpy(#line, #new_line_text); NewLine(); + //if (strlen(#line)*zoom + stolbec > list.column_max)CheckForLineBreak(); + return true; } //============================================================================================ void TWebBrowser::SetStyle() { @@ -309,7 +310,11 @@ void TWebBrowser::SetStyle() { IF(istag("q")) { - if (opened) strcat(#line, " \""); + if (opened) { + meta_encoding = strlen(#line); + if (line[meta_encoding-1] != ' ') chrcat(#line, ' '); + chrcat(#line, '\"'); + } if (!opened) strcat(#line, "\" "); return; } @@ -404,11 +409,11 @@ void TWebBrowser::SetStyle() { if (istag("pre")) || (istag("code")) { style.pre = opened; return; } if (istag("img")) { do{ - if (isattr("src=")) strncpy(#img_path, #val, sizeof(img_path)-1); + if (isattr("src=")) strlcpy(#img_path, #val, sizeof(img_path)-1); if (isattr("title=")) && (strlen(#val) list.column_max) Perenos(); + while (CheckForLineBreak()) {}; DrawStyle(); - line=0; text_color_index--; style.image = false; //ImgCache.Images( left1, draw_y, WB1.list.w); @@ -559,6 +563,7 @@ void TWebBrowser::NewLine() draw_y += list.item_h; if (style.blq) stolbec = 6; else stolbec = 0; if (style.li) stolbec = style.li_tab * 5; + if (debug_mode) debugln(NULL); } //============================================================================================ bool istag(dword text) { if (!strcmp(#tag,text)) return true; else return false; } diff --git a/programs/cmm/TWB/absolute_url.h b/programs/cmm/TWB/absolute_url.h index 91eff4c05..074be7b1b 100644 --- a/programs/cmm/TWB/absolute_url.h +++ b/programs/cmm/TWB/absolute_url.h @@ -14,9 +14,8 @@ void GetAbsoluteURL(dword in_URL) IF (!strncmp(in_URL,"//", 2)) { - //strcpy(#newurl, "http:"); - //strcat(#newurl, in_URL); - sprintf(#newurl, "http:%s", in_URL); + strcpy(#newurl, "http:"); + strcat(#newurl, in_URL); strcpy(orig_URL, #newurl); return; } diff --git a/programs/cmm/TWB/parce_tag.h b/programs/cmm/TWB/parce_tag.h index caae6374d..54d978cdf 100644 --- a/programs/cmm/TWB/parce_tag.h +++ b/programs/cmm/TWB/parce_tag.h @@ -6,6 +6,7 @@ bool GetNextParam() if (!tagparam) return false; if (debug_mode) { + debug("tag: "); debugln(#tag); debug("tagparam: "); debugln(#tagparam); } @@ -23,7 +24,7 @@ bool GetNextParam() //find VAL start and copy i = strrchr(#tagparam, quotes); - strlcpy(#val, #tagparam + i, sizeof(val)); + strlcpy(#val, #tagparam + i, sizeof(val)-1); tagparam[i] = '\0'; i--; //find ATTR end @@ -38,8 +39,8 @@ bool GetNextParam() //find VAL start and copy while (i > 0) && (tagparam[i] != '=') i--; i++; - strlcpy(#val, #tagparam + i, sizeof(val)); - tagparam[i] = '\0'; + strlcpy(#val, #tagparam + i, sizeof(val)-1); + // tagparam[i] = '\0'; //find ATTR end //already have @@ -47,20 +48,22 @@ bool GetNextParam() //find ATTR start and copy while (i>0) && (!__isWhite(tagparam[i])) i--; - strlcpy(#attr, #tagparam + i + 1, sizeof(attr)); + strlcpy(#attr, #tagparam + i + 1, sizeof(attr)-1); tagparam[i] = '\0'; + + //fix case: src=./images/KolibriOS_logo2.jpg?sid=e8ece8b38b + i = strchr(#attr,'='); + if (!quotes) && (i) { + strlcpy(#val, i+1, sizeof(val)-1); + ESBYTE[i+1] = '\0'; + } strlwr(#attr); if (debug_mode) { - if (quotes) { - debug("quote: "); debugch(quotes); debugln(" "); - } - else { - debugln("unquoted text"); - } - sprintf(#param, "val: %s\nattr: %s\n\n", #val, #attr); - debug(#param); + debug("val: "); debugln(#val); + debug("attr: "); debugln(#attr); + debugln(" "); } return true; diff --git a/programs/cmm/TWB/unicode_tags.h b/programs/cmm/TWB/unicode_tags.h index a9dfb1b8b..71d5296b5 100644 --- a/programs/cmm/TWB/unicode_tags.h +++ b/programs/cmm/TWB/unicode_tags.h @@ -65,11 +65,11 @@ char *unicode_tags[]={ 0}; -byte unicode_chars[] = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяЁёhг\243i\105\244\0"; +unsigned char unicode_chars[] = "АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯабвгдежзийклмнопрстуфхцчшщъыьэюяЁёhг\243i\105\244\0"; bool GetUnicodeSymbol(dword in_tag) { - int j; + int j, specia1040; for (j=0; unicode_tags[j]!=0; j+=2;) { @@ -80,10 +80,19 @@ bool GetUnicodeSymbol(dword in_tag) } } - j = atoi(in_tag + 1) - 1040; - if (tag[1] == '1') && (j>=0) && (j<=72) && (strlen(in_tag) == 5) + specia1040 = atoi(in_tag + 1) - 1040; + + if (tag[1] == '1') && (specia1040>=0) + && (specia1040<=72) && (strlen(in_tag) == 5) { - chrcat(#line, unicode_chars[j]); + if (strlen(#line) 0) skin_x_offset = 68; else skin_x_offset = 51; img_draw stdcall(skin.image, address_box.left+address_box.width+1, address_box.top-3, 17, skin.h, skin_x_offset, SKIN_Y); } +void LoadInternalPage(dword bufpos, in_filesize){ + bufsize = in_filesize; + bufpointer = bufpos; + ShowPage(); +} void ShowPage() { DrawOmnibox(); - if (!bufsize) - { - WB1.LoadInternalPage(#page_not_found, sizeof(page_not_found)); + if (!bufsize) || (!bufpointer) { + LoadInternalPage(#page_not_found, sizeof(page_not_found)-1); } - else - { - WB1.Prepare(); + WB1.Prepare(); + if (source_mode) { + source_mode = false; + ShowSource(); + LoadInternalPage(bufpointer, bufsize); } } @@ -698,6 +698,14 @@ void EventOpenDialog() } } +void EventViewSource() +{ + char source_view_param[sizeof(URL)+4]; + strcpy(#source_view_param, "-s "); + strcat(#source_view_param, #URL); + RunProgram(#program_path, #source_view_param); +} + void DrawStatusBar(dword _status_text) { status_text.start_x = 10; diff --git a/programs/cmm/browser/history.h b/programs/cmm/browser/history.h index b8d108645..8add45fc5 100644 --- a/programs/cmm/browser/history.h +++ b/programs/cmm/browser/history.h @@ -23,37 +23,37 @@ ShowHistory() { - int i; - static int history_pointer; - int t; + int i; + static int history_pointer; + int t; + + free(history_pointer); + history_pointer = malloc(history.items.data_size+256); + strcat(history_pointer, HISTORY_HEADER); + for (i=0; i"); + strcat(history_pointer, history.items.get(i)); + strcat(history_pointer, "
"); + } + /* + strcat(history_pointer, "
Cached images
"); + for (i=1; i"); + strcat(history_pointer, #pics[i].path); + strcat(history_pointer, "
"); - free(history_pointer); - history_pointer = malloc(history.items.data_size+256); - strcat(history_pointer, HISTORY_HEADER); - for (i=0; i"); - strcat(history_pointer, history.items.get(i)); - strcat(history_pointer, "
"); - } - /* - strcat(history_pointer, "
Cached images
"); - for (i=1; i"); - strcat(history_pointer, #pics[i].path); - strcat(history_pointer, "
"); - - // strcat(history_pointer, "
"); - // strcat(history_pointer, #pics[i].path); - } - */ - strcat(history_pointer, ""); - WB1.LoadInternalPage(history_pointer, strlen(history_pointer)); + // strcat(history_pointer, "
"); + // strcat(history_pointer, #pics[i].path); + } + */ + strcat(history_pointer, ""); + LoadInternalPage(history_pointer, strlen(history_pointer)); } \ No newline at end of file diff --git a/programs/cmm/browser/html/homepage_ru.htm b/programs/cmm/browser/html/homepage_ru.htm index 803a12b56..d43571764 100644 --- a/programs/cmm/browser/html/homepage_ru.htm +++ b/programs/cmm/browser/html/homepage_ru.htm @@ -9,7 +9,7 @@ 3. Kolibri Store Для поиска в Google наберите тест в адресной строке -и нажмите Ctrl+Enter. Есть также другие Горячие клавиши. +и нажмите Ctrl+Enter. Есть также другие Горячие клавиши. diff --git a/programs/cmm/browser/show_src.h b/programs/cmm/browser/show_src.h index 742607e84..e4a643a23 100644 --- a/programs/cmm/browser/show_src.h +++ b/programs/cmm/browser/show_src.h @@ -1,231 +1,95 @@ -enum { TAG, OPTION_VALUE, TEXT, COMMENT, SCRIPT}; +dword source_buf_start, source_buf_end; +int opened_font=0; +int mode; + +void SourceBufAdd(dword _mode, src) +{ + dword font_found_pointer, src_orig = src; + + if (_mode) mode = _mode; + + strcpy(source_buf_end, src); + source_buf_end += strlen(source_buf_end); + + if (font_found_pointer = strstr(src, "")) { + opened_font--; + src = font_found_pointer+2; + } + + src = src_orig; + if (font_found_pointer = strstr(src, ""); +} + +enum { TAG=1, VALUE, TEXT, COMMENT, SCRIPT}; dword ShowSource() { - dword new_buf, new_buf_start, i, j; - int opened_font=0; - int mode = TEXT; + dword i, j; + bool activate_script_mode = false; - if (souce_mode) return; - souce_mode = true; - new_buf = malloc(bufsize*5); - new_buf_start = new_buf; + opened_font=0; + source_buf_start = source_buf_end = malloc(bufsize*5); header[strrchr(#header, '-')-2]=0; - sprintf(new_buf,"Source: %s
",#header);
-	new_buf += strlen(new_buf);
-	for (i=bufpointer; iSource: ");
+	SourceBufAdd(TEXT, #header);
+	SourceBufAdd(TEXT, "
");
+
+	for (i=bufpointer; i<script"); opened_font++;
-					new_buf+=54;
-					i+=6;
-					break;
+		case '<':
+			if (!strncmp(i+1,"!--", 3)) SourceBufAdd(COMMENT, "<");
+			else if (SCRIPT == mode) {
+				if (!strncmp(i+1,"/script>", 8)) {
+					CloseAllOpenedFonts(NULL);
+					SourceBufAdd(TAG, "<");
 				}
-				if (mode == COMMENT) || (mode == SCRIPT) && (!strncmp(i+1,"/script>", 8)) {
-					mode = TEXT;
-					while (opened_font) {
-						strcpy(new_buf, ""); opened_font--;
-						new_buf+=7;						
-					}
-					strcpy(new_buf, "</script>"); 
-					new_buf+=39;
-					i+=8;
-					break;
-				}
-				if (ESBYTE[i+1]=='!') && (ESBYTE[i+2]=='-') && (ESBYTE[i+3]=='-') {
-					mode = COMMENT;
-					strcpy(new_buf, "<"); opened_font++;
-					new_buf+=21;
-					break;
-				}
-				if (mode == TEXT) {
-					mode = TAG;
-					strcpy(new_buf, "<"); opened_font++;
-					new_buf+=21;
-					break;
-				}
-				if (mode == COMMENT) || (mode == SCRIPT) {
-					strcpy(new_buf, "<");
-					new_buf+=4;
-					break;
-				}
-				break;
-			case '>':
-				if (mode == OPTION_VALUE) { //fix non-closed quote in TAG
-					mode = TEXT;
-					while (opened_font) {
-						strcpy(new_buf, """); opened_font--;
-						new_buf+=13;						
-					}
-					break;
-				}
-				if (mode == COMMENT) && (ESBYTE[i-1]=='-') && (ESBYTE[i-2]=='-') {
-					mode = TEXT;
-					strcpy(new_buf, ">"); opened_font--;
-					new_buf+=11;
-					break;
-				}
-				if (mode == COMMENT) || (mode == SCRIPT) {
-					strcpy(new_buf, ">");
-					new_buf+=4;
-					break;					
-				}
-				if (mode == TAG) {
-					mode = TEXT;
-					strcpy(new_buf, ">"); opened_font--;
-					new_buf+=11;
-					break;
-				}
-				break;
-			case '\"':
-			case '\'':
-				if (mode == TAG) {
-					mode = OPTION_VALUE;
-					strcpy(new_buf, "'"); opened_font++;
-					new_buf+=25;
-					break;
-				}
-				if (mode == OPTION_VALUE) {
-					mode = TAG;
-					strcpy(new_buf, "'"); opened_font--;
-					new_buf+=12;
-					break;
-				}
-			default:
-				ESBYTE[new_buf] = ESBYTE[i];
-				new_buf++;
-		}
+				else SourceBufAdd(NULL, "<");
+			}
+			else if (COMMENT == mode) {
+				SourceBufAdd(NULL, "<");
+			}
+			else if (TEXT == mode) {
+				if (!strncmp(i+1,"script", 6)) activate_script_mode = true;
+				SourceBufAdd(TAG, "<");
+			}
+			break;
+		case '>':
+			if (TAG == mode) && (activate_script_mode) {
+				activate_script_mode = false;
+				SourceBufAdd(SCRIPT, ">");
+			}
+			else if (VALUE == mode) CloseAllOpenedFonts(TEXT);
+			else if (COMMENT == mode) && (!strncmp(i-2,"--", 2)) {
+				SourceBufAdd(TEXT, ">");
+				CloseAllOpenedFonts(TEXT);
+			}
+			else if (COMMENT == mode) || (SCRIPT == mode) SourceBufAdd(NULL, ">");
+			else if (TAG == mode) SourceBufAdd(TEXT, ">");
+			break;
+		case '&':
+			SourceBufAdd(NULL, "&");
+			break;
+		case '\"':
+		case '\'':
+			if (TAG == mode) SourceBufAdd(VALUE, "'");
+			else if (VALUE == mode) SourceBufAdd(TAG, "'");
+			else SourceBufAdd(NULL, "'");
+			break;
+		default:
+			ESBYTE[source_buf_end] = ESBYTE[i];
+			source_buf_end++;
 	}
-	ESBYTE[new_buf] = 0;
-	bufsize = new_buf - new_buf_start;
+	ESBYTE[source_buf_end] = 0;
+	bufsize = source_buf_end - source_buf_start;
 	free(bufpointer);
-	bufpointer = new_buf_start;
+	bufpointer = source_buf_start;
 }
-
-/*
-
-enum { TAG, OPTION_VALUE, TEXT, COMMENT, INLINE_COMMENT, CODE };
-
-char* C_HL_keywords[] = {
-    "switch", "if", "while", "for", "break", "continue", "return", "else",
-    "union", "typedef", "static", "class", "case", "#include",
-    "volatile", "register", "sizeof", "typedef", "union", "goto", "const", "auto",
-    "#define", "#endif", "#error", "#ifdef", "#ifndef", "#undef", "#if", "#else", 
-    "inline", 
-
-    "int ", "dword ", "long ", "double ", "float ", "char ", "unsigned ", "signed ",
-    "void ", "bool ", "enum ", "byte ", "word ", "struct ", "NULL", "loop", "stdcall ",
-    ":void ", ":int ", ":bool ", ":dword ", NULL
-};
-
-dword ShowCodeSource()
-{
-	dword new_buf, new_buf_start, i;
-	int mode = CODE;
-
-	char spstr[64];
-	dword keylen;
-	dword keyn;
-	dword keycolor;
-
-	new_buf = malloc(bufsize*10);
-	new_buf_start = new_buf;
-	sprintf(new_buf,"C/C++/C-- source: %s
",#URL);
-	new_buf += strlen(new_buf);
-	for (i=bufpointer; i' == ESBYTE[i]) {
-			strcpy(new_buf, ">");
-			new_buf+=4;
-			continue;
-		}
-		if (ESBYTE[i] >= '0') && (ESBYTE[i] <= '9') && (CODE == mode) {
-			strcpy(new_buf, "?");
-			ESBYTE[new_buf+20] = ESBYTE[i];
-			new_buf+=28;
-			if (ESBYTE[i+1] == 'x') {
-				strcpy(new_buf, "x");
-				new_buf+=28;
-				i++;
-			}
-			continue;
-		}
-
-		if (CODE == mode) && ('\"' == ESBYTE[i]) {
-			mode = TEXT;
-			strcpy(new_buf, "\"");
-			new_buf+=18;
-			continue;
-		}
-		if (TEXT == mode) && ('\"' == ESBYTE[i]) {
-			mode = CODE;
-			strcpy(new_buf, "\"");
-			new_buf+=8;
-			continue;		
-		}
-
-		if (! strncmp(i, "//", 2) ) && (mode == CODE) {
-			mode = INLINE_COMMENT;
-			strcpy(new_buf, "//");
-			new_buf+=19;
-			i++;
-			continue;
-		}
-
-		if (INLINE_COMMENT == mode) {
-			if (13 == ESBYTE[i]) {
-				mode = CODE;
-				strcpy(new_buf, "\13");
-				new_buf+=8;
-				continue;				
-			}
-		}
-
-		if (! strncmp(i, "/*", 2) ) {
-			mode = COMMENT;
-			strcpy(new_buf, "/*");
-			new_buf+=19;
-			i++;
-			continue;
-		}
-		if (! strncmp(i, "*/", 2) ) {
-			mode = CODE;
-			strcpy(new_buf, "*/");
-			new_buf+=9;
-			i++;
-			continue;
-		}
-
-		if (CODE == mode) for (keyn=0; C_HL_keywords[keyn]!=NULL; keyn++) 
-		{
-			keylen = strlen(C_HL_keywords[keyn]);
-			if (! strncmp(i, C_HL_keywords[keyn], keylen) ) {
-
-				if (keyn<31) keycolor="#f00"; else keycolor="#00f";
-				sprintf(#spstr, "%s", keycolor, C_HL_keywords[keyn]);
-				strcpy(new_buf, #spstr);
-
-				new_buf += keylen + 24;
-				i += keylen-1;
-				goto _CONTINUE;
-			}
-		}
-		ESBYTE[new_buf] = ESBYTE[i];
-		new_buf++;
-		_CONTINUE:		
-	}
-	ESBYTE[new_buf] = 0;
-	bufsize = new_buf - new_buf_start;
-	free(bufpointer);
-	bufpointer = new_buf_start;
-}
-*/
\ No newline at end of file
diff --git a/programs/cmm/codeview/codeview.c b/programs/cmm/codeview/codeview.c
index 14efcff18..8df6c5db9 100644
--- a/programs/cmm/codeview/codeview.c
+++ b/programs/cmm/codeview/codeview.c
@@ -193,7 +193,7 @@ void OpenPage()
 	if (!strncmp(#URL,"CodeView:",8))
 	{
 		SetPageDefaults();
-		if (!strcmp(#URL, URL_SERVICE_HOME)) WB1.LoadInternalPage(#homepage, sizeof(homepage));
+		if (!strcmp(#URL, URL_SERVICE_HOME)) LoadInternalPage(#homepage, sizeof(homepage));
 		DrawEditBoxWebView();
 		return;
 	}
@@ -208,7 +208,7 @@ void OpenPage()
 			SetPageDefaults();
 			ReadFile(0, bufsize, bufpointer, #URL);
 			ShowCodeSource();
-			WB1.LoadInternalPage(bufpointer, bufsize);	
+			LoadInternalPage(bufpointer, bufsize);	
 		}
 		ShowPage();
 	}
@@ -226,18 +226,17 @@ DrawEditBoxWebView()
 	img_draw stdcall(skin.image, address_box.left+address_box.width+1, address_box.top-3, 17, skin.h, skin_x_offset, SKIN_Y);
 }
 
+void LoadInternalPage(dword bufpos, in_filesize){
+	bufsize = in_filesize;
+	bufpointer = bufpos;
+	ShowPage();
+}
 
 void ShowPage()
 {
 	DrawEditBoxWebView();
-	if (!bufsize)
-	{
-		WB1.LoadInternalPage(#page_not_found, sizeof(page_not_found));
-	}
-	else
-	{
-		WB1.Prepare();
-	}
+	if (!bufsize) LoadInternalPage(#page_not_found, sizeof(page_not_found));
+	WB1.Prepare();
 }
 
 void DrawStatusBar() {return;};
diff --git a/programs/cmm/dicty/dicty.c b/programs/cmm/dicty/dicty.c
index 736ebd229..a421eb407 100644
--- a/programs/cmm/dicty/dicty.c
+++ b/programs/cmm/dicty/dicty.c
@@ -154,7 +154,7 @@ void DrawTranslation()
 {
 	int y_pos=TOPH+1;
 	char draw_buf[4096];
-	strlcpy(#draw_buf, #translate_result, sizeof(draw_buf));
+	strlcpy(#draw_buf, #translate_result, sizeof(draw_buf)-1);
 	
 	DrawBar(0, y_pos, Form.width-9, Form.cheight - y_pos, 0xFFFFFF);
 	strttl(#draw_buf);
diff --git a/programs/cmm/lib/kolibri.h b/programs/cmm/lib/kolibri.h
index 6d335fe17..0f2b8a6d1 100644
--- a/programs/cmm/lib/kolibri.h
+++ b/programs/cmm/lib/kolibri.h
@@ -28,6 +28,7 @@ char program_path[4096];
 #define bool      int
 
 #define NULL      0
+#define EOS       0
 #define OLD      -1
 #define true      1
 #define false     0
diff --git a/programs/cmm/lib/strings.h b/programs/cmm/lib/strings.h
index a3fd769a5..cd6826c2c 100644
--- a/programs/cmm/lib/strings.h
+++ b/programs/cmm/lib/strings.h
@@ -395,37 +395,23 @@ inline fastcall void strcat( EDI, ESI)
     }
 }
 
-:void strncat(dword text1, text2, signed len)
-signed o1,o2;
-char s;
+:void strncat(dword dst, src, dword len)
 {
-	s = DSBYTE[text1];
-	while(s){
-		$inc text1
-		s = DSBYTE[text1];
+	while (ESBYTE[dst]) dst++;
+	while (ESBYTE[src]) && (len) {
+		ESBYTE[dst] = ESBYTE[src];
+		dst++;
+		src++;
+		len--;
 	}
-	o1 = len/4;
-	o2 = len-4*o1;
-	while(o1){
-		DSDWORD[text1] = DSDWORD[text2];
-		text1 += 4;
-		text2 += 4;
-		$dec o1
-	}
-	while(o2){
-		DSBYTE[text1] = DSBYTE[text2];
-		$inc text1 
-		$inc text2 
-		$dec o2
-	}
-	DSBYTE[text1] = 0;
 }
 
-inline fastcall void chrcat(ESI, BL)
+inline fastcall void chrcat(ESI, DI)
 {
-    EDI = strlen(ESI);
-    ESBYTE[ESI+EDI] = BL;
-    ESBYTE[ESI+EDI+1] = 0;
+    while (ESBYTE[ESI]) ESI++;
+    ESBYTE[ESI] = DI;
+    ESI++;
+    ESBYTE[ESI] = 0;
 }
 
 inline dword strchr(dword shb;char s)