Problem z polskimi znakami

0

Witam.
Mam mały problem - otóż korzystam z unitu DOS, który wykorzystuje m.in. do pobierania nazwy plików w danej lokalizacji na dysku i wyświetlaniu ich - coś jak polecenia "dir" lub "ls". Kiedy można mój program dzieli pliki na kolumny. Do ustawiania kolumn, tak aby były w jednej linii używam length od tej nazwy i parę innych przeliczeń. Kiedy w nazwie pliku znajdują się polskie znaki są pomijane przy przeliczaniu odstępu, co powoduje przesunięcie w lewo o ilość polskich znaków. Chciałbym się zapytać, czy winna jest tutaj funkcja length, czy może struktura SearchRec, która przechowuje informacje o pliku. Będę wdzięczny za wskazówki do rozwiązania tego (pewnie prymitywnego) problemu.
Pozdrawiam.

0

DOS to przeżytek. Czy nie możesz po ludzku skorzystać z modułu Windows i zawartych w nim funkcji FindFirstFile oraz FindNextFile? Na pewno wtedy też zniknie problem z polskimi znakami w nazwie pliku. A jeśli nawet te wyświetlają się one nadal nieprawidłowo, to istnieje przecież funkcja AnsiToOEM, który może rozwiązać problem przy wyświetleniu znaków w konsoli.

0

DOS to przeżytek
"korzystam z unitu DOS" nie oznacza "korzystam z DOS-a". Tak ten unit się historycznie używa, wewnętrznie przecież i tak wykorzystuje te same funkcje WinAPI z modułu Windows.
A jest jeszcze unit sysutils.

(zakładam że mówimy o FPC dla Win32...)

Kiedy w nazwie pliku znajdują się polskie znaki są pomijane przy przeliczaniu odstępu
kodddddd

0

Postawiłem sobie za cel, że aplikację napiszę na crt, dosie i niczym więcej. Ponadto aplikacja śmiga na linuksie, tak więc moduł Windows raczej odpada. Być może mało zrozumiale opisałem swój problem - nazwy plików wyświetlają się poprawnie, lecz kiedy są w niej polskie znaki źle obliczane jest wyrównanie do następnej kolumny odpowiednio o n mniej znaków polskich w nazwie pliku.

Mój kod obliczający odstęp:

if not(((i=cols) or (i=1)) and (WhereX+spacer-length(S.Name)>=ScreenWidth)) THEN
						for k:=1 to spacer-length(S.Name) do 
							write(#32); 

spacer to najdłuższa nazwa pliku +1
Jak to wygląda w praktyce:
![Zrzut ekranu z 2013-01-14 2124.png](//static.4programmers.net/uploads/attachment/Zrzut ekranu z 2013-01-14 2124.png)

1

Użyj UTF8String, i dopiero tego stringu mierz długość.

0

Właśnie chodzi o to, że nie za bardzo mogę go użyć ponieważ rekord SearchRec, ma pole "Name"(nazwa pliku), które jest zwykłym stringiem - rzutowałem to na ANSI String i nic nie daje, UTF8 też nie. Raczej chodzi mi o to, aby podmienić to pole w rekordzie lub przeciążyć funkcje length(choć to chyba nie ma sensu) tylko nie wiem jak. Procedury FindNext itd przyjmują parametry tylko z unitu DOS więc utworzenie swojej struktury odpada.

0

które jest zwykłym stringiem
Ale zakodowanym zapewne w UTF-8, bo to jest obecnie standardem w Linuksie.
Nie pamiętam czy FPC ma coś wbudowane do dekodowania UTF-8, ale nawet jeśli nie, to algorytm nie jest trudny.
Ogólnie to trzeba zdekodować UTF-8 do UCS-4 i wtedy dopiero zliczyć znaki.

(idealnie byłoby jeszcze pomijać wszelkie „combining” i „zero-width” ale już nie wymagajmy...)

0

http://wiki.freepascal.org/Theodp
Na dole strony jest załącznik. W pliku utf8scanner.pas zdefiniowana jest klasa TUTF8Scanner która ma między innymi metodę Length więc mozesz jej użyć (przykład poniżej) a jak nie chcesz tworzyć klasy to oblukaj źródła i przerób to sobie na zwykła funkcję.

const
  STR_TEST = 'abc123_?!& ąćęłńóśźż'; //powinno wyjsc 20
var
  utf8Scan: TUTF8Scanner;
begin
  utf8Scan:= TUTF8Scanner.Create(STR_TEST);
  try
  ShowMessage(IntToStr(utf8Scan.Length));
  finally
    utf8Scan.Free;
  end
end;

1 użytkowników online, w tym zalogowanych: 0, gości: 1