diff --git a/hwe/b_genList.php b/hwe/b_genList.php index 1d39d0b0..64a54a62 100644 --- a/hwe/b_genList.php +++ b/hwe/b_genList.php @@ -171,7 +171,7 @@ for($j=0; $j < $gencount; $j++) { $turn = getTurn($general, 1, 0); for($i=0; $i < 5; $i++) { - $turn[$i] = StringUtil::SubStrForWidth($turn[$i], 0, 20); + $turn[$i] = StringUtil::subStringForWidth($turn[$i], 0, 20); $k = $i+1; echo "  $k : $turn[$i]
"; diff --git a/hwe/c_double.php b/hwe/c_double.php index 7014b392..b5d86a4f 100644 --- a/hwe/c_double.php +++ b/hwe/c_double.php @@ -33,7 +33,7 @@ if($command == 46) { $name = str_replace(" ", "", $name); $name = str_replace(" ", "뷁", $name); if($name == "") { $name = "무명"; } - $name = StringUtil::SubStrForWidth($name, 0, 12); + $name = StringUtil::subStringForWidth($name, 0, 12); $db->update('general', [ 'makenation'=>$name @@ -58,7 +58,7 @@ if($command == 46) { $nationname = str_replace(" ", "", $nationname); $nationname = str_replace(" ", "뷁", $nationname); if($nationname == "") { $nationname = "무명"; } - $nationname = StringUtil::SubStrForWidth($nationname, 0, 12); + $nationname = StringUtil::subStringForWidth($nationname, 0, 12); $query = "update general set makenation='{$nationname}' where level>=5 and nation='{$me['nation']}'"; MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); @@ -84,7 +84,7 @@ if($command == 46) { $note = str_replace("|", "", $note); $note = str_replace(" ", "", $note); $note = str_replace(" ", "뷁", $note); - $note = StringUtil::SubStrForWidth($note, 0, 90); + $note = StringUtil::subStringForWidth($note, 0, 90); $query = "update diplomacy set reserved='{$note}' where me='{$me['nation']}' and you='$double'"; MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); diff --git a/hwe/func_npc.php b/hwe/func_npc.php index 994fa84d..87a4fd0e 100644 --- a/hwe/func_npc.php +++ b/hwe/func_npc.php @@ -423,7 +423,7 @@ function processAI($no) { $colors = GetNationColors(); $color = rand() % count($colors); $command = EncodeCommand(0, $type, $color, 46); - $nationName = "㉿".StringUtil::SubStr($general['name'], 1); + $nationName = "㉿".mb_substr($general['name'], 1); //건국 $query = "update general set turn0='$command',makenation='$nationName' where no='{$general['no']}'"; MYDB_query($query, $connect) or Error("processAI08 ".MYDB_error($connect),""); diff --git a/hwe/func_process_personnel.php b/hwe/func_process_personnel.php index e2ff16f9..417f99e5 100644 --- a/hwe/func_process_personnel.php +++ b/hwe/func_process_personnel.php @@ -787,7 +787,7 @@ function process_55(&$general) { $result = MYDB_query($query, $connect) or Error(__LINE__.MYDB_error($connect),""); $nationcount = MYDB_num_rows($result); - if($nationcount > 0) { $makename = StringUtil::SubStr("$nationcount".$general['name'], 0, 6); } + if($nationcount > 0) { $makename = mb_substr("$nationcount".$general['name'], 0, 6); } else { $makename = $general['name']; } if($general['level'] != 0) { diff --git a/hwe/process_war.php b/hwe/process_war.php index 4a08e1f9..5da8f5a3 100644 --- a/hwe/process_war.php +++ b/hwe/process_war.php @@ -400,7 +400,7 @@ function processWar($general, $city) { } $render_attacker = [ - 'crewtype' => StringUtil::SubStr(GameUnitConst::byId($general['crewtype'])->name, 0, 2), + 'crewtype' => mb_substr(GameUnitConst::byId($general['crewtype'])->name, 0, 2), 'name'=> $general['name'], 'remain_crew' => $general['crew'], 'killed_crew' => -$mydeathnum @@ -1276,13 +1276,13 @@ function processWar($general, $city) { } $render_attacker = [ - 'crewtype' => StringUtil::SubStr(GameUnitConst::byId($general['crewtype'])->name, 0, 2), + 'crewtype' => mb_substr(GameUnitConst::byId($general['crewtype'])->name, 0, 2), 'name'=> $general['name'], 'remain_crew' => $general['crew'], 'killed_crew' => -$mydeathnum ]; $render_defender = [ - 'crewtype' => StringUtil::SubStr(GameUnitConst::byId($oppose['crewtype'])->name, 0, 2), + 'crewtype' => mb_substr(GameUnitConst::byId($oppose['crewtype'])->name, 0, 2), 'name'=> $oppose['name'], 'remain_crew' => $oppose['crew'], 'killed_crew' => -$opdeathnum diff --git a/src/sammo/StringUtil.php b/src/sammo/StringUtil.php index 79e07d74..24e8f3a3 100644 --- a/src/sammo/StringUtil.php +++ b/src/sammo/StringUtil.php @@ -3,169 +3,75 @@ namespace sammo; class StringUtil { - public static function GetStrLen($str) + /** + * 전각, 반각 길이 기준의 substr + * @param string $str 원본 문자열 + * @param int $start 시작 너비. 일치하는 문자가 없을 경우 그 다음 문자부터. 음수의 경우 뒤에서부터. + * @param int|null $width 길이. null일 경우 끝까지. + */ + public static function subStringForWidth(string $str, int $start = 0, $width = null) { - $count = strlen($str); - $len = 0; - for ($i=0; $i < $count;) { - $code = ord($str[$i]); - - if ($code >= 0xf0) { - $len++; - $i += 4; - } elseif ($code >= 0xe0) { - $len++; - $i += 3; - } elseif ($code >= 0xc2) { - $len++; - $i += 2; - } else { - $len++; - $i += 1; - } + $length = mb_strwidth($str, 'UTF-8'); + if($width === null){ + $width = $length; } - return $len; + + if($start < 0){ + $start = $length - $start; + } + + /* 길이를 직관적으로 알아낼 수 있는 방법은 '없다'. + * utf8의 경우 뒤에서부터 세는 것 전략이 가능하나 제외함. + */ + + $currentPos = 0; + $currentWidth = 0; + + $strings = static::splitString($str); + foreach($strings as $idx=>$char){ + $charWidth = mb_strwidth($char, 'UTF-8'); + if($currentPos+$charWidth > $start){ + break; + } + $currentPos += $charWidth; + } + + if($currentPos + $width >= $length){ + return substr($str, $currentPos, null); + } + + for($idx = $currentPos; $idx < count($strings); $idx++){ + $char = $strings[$idx]; + + $charWidth = mb_strwidth($char, 'UTF-8'); + if($currentWidth + $charWidth > $width){ + break; + } + $currentWidth += $charWidth; + } + + return substr($str, $currentPos, $currentWidth); } - public static function SubStr($str, $s, $l=1000) + public static function cutStringForWidth(string $str, int $width, string $endFill='..') { - $count = strlen($str); - $startByte = 0; - $isSet = 0; - $endByte = $count; - $len = 0; - for ($i=0; $i < $count;) { - $code = ord($str[$i]); + if(mb_strwidth($str) <= $width){ + return $str; + } - if ($isSet == 0 && $len >= $s) { - $startByte = $i; - $isSet = 1; - } - if ($isSet == 1 && $len-$s >= $l) { - $endByte = $i; + $result = ''; + $width -= mb_strwidth($endFill, 'UTF-8'); + + foreach(static::splitString($str) as $char){ + $charWidth = mb_strwidth($char, 'UTF-8'); + if($charWidth > $width){ break; } - - if ($code >= 0xf0) { - $len++; - $i += 4; - } elseif ($code >= 0xe0) { - $len++; - $i += 3; - } elseif ($code >= 0xc2) { - $len++; - $i += 2; - } else { - $len++; - $i += 1; - } + $result .= $char; + $width -= $charWidth; } - $str = substr($str, $startByte, $endByte-$startByte); - return $str; - } - public static function SubStrForWidth($str, $s, $w) - { - $count = strlen($str); - $startByte = 0; - $isSet = 0; - $endByte = $count; - $last = 0; - $len = 0; - $width = 0; - for ($i=0; $i < $count;) { - $code = ord($str[$i]); - - if ($isSet == 0 && $len >= $s) { - $startByte = $i; - $isSet = 1; - $width = 0; - } - if ($isSet == 1 && $width == $w) { - $endByte = $i; - break; - } - if ($isSet == 1 && $width > $w) { - $endByte = $i - $last; - break; - } - - if ($code >= 0xf0) { - $len++; - $width += 2; - $last = 4; - $i += 4; - } elseif ($code >= 0xe0) { - $len++; - $width += 2; - $last = 3; - $i += 3; - } elseif ($code >= 0xc2) { - $len++; - $width += 2; - $last = 2; - $i += 2; - } else { - $len++; - $width += 1; - $last = 1; - $i += 1; - } - } - $str = substr($str, $startByte, $endByte-$startByte); - return $str; - } - - public static function CutStrForWidth($str, $s, $w, $ch='..') - { - $isCut = 0; - $count = strlen($str); - $startByte = 0; - $isSet = 0; - $endByte = $count; - $last = 0; - $len = 0; - $width = 0; - for ($i=0; $i < $count;) { - $code = ord($str[$i]); - - if ($isSet == 0 && $len >= $s) { - $startByte = $i; - $isSet = 1; - $width = 0; - } - if ($isSet == 1 && $width >= $w) { - $endByte = $i - $last; - $isCut = 1; - break; - } - - if ($code >= 0xf0) { - $len++; - $width += 2; - $last = 4; - $i += 4; - } elseif ($code >= 0xe0) { - $len++; - $width += 2; - $last = 3; - $i += 3; - } elseif ($code >= 0xc2) { - $len++; - $width += 2; - $last = 2; - $i += 2; - } else { - $len++; - $width += 1; - $last = 1; - $i += 1; - } - } - if ($isCut != 0) { - $str = substr($str, $startByte, $endByte-$startByte) . $ch; - } - return $str; + return $result.$endFill; } function splitString($str, $l = 0) { @@ -228,12 +134,10 @@ class StringUtil return static::padString($str, $maxsize, $ch, 0); } - public static function EscapeTag($str) + public static function escapeTag($str) { $str = htmlspecialchars($str); $str = str_replace(["\r\n", "\r", "\n"], '
', $str); -// return nl2br(htmlspecialchars($str)); -// return htmlspecialchars($str); return $str; }