Article View: pl.comp.lang.c
Article #1618Edytor tekstu
From: Marcin Zielinski
Date: Wed, 18 Feb 1998 07:33
Date: Wed, 18 Feb 1998 07:33
137 lines
6074 bytes
6074 bytes
Mam problem z napisaniem edytora tekstu.
Mój edytor ma wczytywać dane z pliku HTML i wyświetlać na ekranie tekst, w
którym zaznaczone by były znaczniki tego języka. Ja już próbowałem i
przedstawię Ci moje rozwiązanie, które jest dobre, ale przy dokumentach
mających długie linie (po 600 znaków) strasznie szwankuje szybkość rysowania
tekstu. Poza małą prędkością mój algorytm nie radzi sobie z np: łamaniem
lini kodu HTML tzn. jeśli na przykład mamy taki fragment kodu HTML:
<body
background="ala.gif">
to zostanie podświetlone tylko słowo body, a reszta będzie traktowana jak
zwykły tekst.
Napisałem już kawałek programu wyświetlającego ten tekst, dlatego poniżej
przedstawię Ci to co udało mi się zrobić.
(Program pisany jest w Visual C++)
Zdefiniowałem klasę CHTMLEditorDoc, w której dodałem zmienną CStringArray
lines przechowywującą linie tekstu.
Zdefiniowałem również klasę CHTMLEditorView, odpowiedzialną, za wyświetlanie
tekstu w okienku. (dziedziczy ona po klasie CScrollView), a o to dodane
przezemnie funkcje i składowe:
const fs_FormatChar = 0x10;
const fs_Normal = 0x11;
class CFranekView : public CScrollView
{
public: // Funkcje obslugi slow kluczowych
static CObArray *keyWords; // Keywords - slowa kluczowe, ktore np: beda
podswietlane
static CKeyWord *FindKeyWord(char *keyWord); // Odszukuje slowo kluczowe
protected: // create from serialization only
// Zmienne mające za zadanie przyśpieszyć rysowanie na ekranie. Funkcja
OnDraw rysuje tylko tyle ile jest
// widziane na ekranie
int charsVisible; // ilość znaków widzianych
int linesVisible; // ilość lini widzianych
public:
int topLine, bottomLine; // Numer gornej i dolnej widocznej na ekranie lini
protected:
CFont *font; // Czcionka, którą ma być wyświetlany tekst
private:
CSize fontSize; // Rozmiary czcionki. Potrzebne by dokładnie pozycjonować
kursor w czasie edycji
int FindChar(LPCSTR text, char c, int start); // Funkcja przyśpieszająca
wyszukiwanie znaków
void DrawLine(CDC *pDC, CPoint pos, LPCSTR str); // funkcja rysuje na dane
pozycji tekst z parametru str
CString FormatString(LPCSTR string);
.
.
.
.
};
W tej klasie znajduje się również funkcja OnDraw(CDC *pDC), którą
zaimplementowałem tak:
CFranekDoc* pDoc = GetDocument(); // Pobiera wskaznik do dokumentu
ASSERT_VALID(pDoc); // Dodane przez VC++
pDC->SetBkMode(TRANSPARENT);
for (int i = topLine; i < bottomLine; i++)
{
CString line; // Linia, ktora jest poddawana obrobce
if (i > pDoc->lines.GetSize() - 1) break; // Zabezpieczenie przed wyjsciem
poza zakres tablicy lines
line = ((CLine *)pDoc->lines[i])->lineText; // Kopiuje linie, ktora ma byc
rysowana
CString formatedString = ""; // Linia sformatowana, dla funkcji DrawLine
BOOL section = FALSE; // Informacja o tym, że jest teraz sekcja HTML
int j = 0;
int lineLength = line.GetLength(); // Za zadanie ma przyśpieszyć funkcję
while (j < lineLength)
{
if (line[j] == '<') // Czy znacznik HTML
{
section = TRUE; // Zaczyna się sekcja HTML
formatedString += line.Left(j) + FS_RESTORE; // Do tekstu formatowanego
kopiuje cały tekst wcześniejszy, który nie jest tekstem HTML'a
int k = lineLength - j;
if (k > 0)
line = line.Right(k); // Obcina linie do znaku <
else
line = ""; // Jezeli dlugość pozostałej linii jest 0
lineLength = line.GetLength();
j = 0;
} else
if ((line[j] == '>') & (section)) // Jezeli znak kończący sekcję
{
formatedString += FormatString(line.Left(j + 1)); // Wywołuje funckcję
formatującą , która zwraca tekst sformatowany
line = line.Right(line.GetLength() - j - 1); // Obcina znowu linie, bo
już
lineLength = line.GetLength();
section = FALSE;
j = 0;
};
j++;
};
formatedString += line + FS_RESTORE; // FS_RESTORE mówi, że tekst po tym
znaczniku ma być rysowany
// czcionką domyślną
DrawLine(pDC, CPoint(0, i), formatedString); // Rysuje linie na ekranie
};
Funkcja FormatString szuka słów, jeśli okaże się, że dane słowo jest słowem
HTML'a to wstawia znaczniki formatowania przed danym słowem. Format
znaczników jest taki:
znak fs_FormatChar (mówiący, że dalej zaczyna się informacja o czcionce)
jeśli po tym znaczniku znajduje się znacznik fs_Normal to przywracana jest
czcionka domyślna, jeśli nie to po kolei zapisywane są bajty: pogrubienie,
pochyłość, oraz na końcu trzy składowe koloru powiększone o 1 (by nie było
znaku końca łancucha dla np: koloru 0x000000).
Funkcja DrawLine przeszukuje tekst z parametru str i gdy znajdzie znak
fs_FormatChar ustawia odpowiednią czcionkę. Gdy znajdzie znak fs_FormatChar,
a po nim znak fs_Normal to rysuje tekst do tych dwóch znaków i ustawia
domyślną czcionkę.
Algorytm jest nawet sprawny, gdyby nie to, że musi on tyle razy przeszukiwać
dane łańcuchy. Nawet wstawki w assemblerze nie rozwiązuję tego problemu.
Ponieważ nie za dobże potrafię tłumaczyć co mi chodzi po głowie, dlatego
jeśli czegoś nie będziesz wiedział napisz do mnie.
Proszę o pomoc, za którą z góry dziękuję.
------------------------------------------
Marcin Zielinski
e-mail: zielu1@polbox.com
e-mail: zielu1@friko3.onet.pl
http://free.polbox.pl/z/zielu1
http://friko3.onet.pl/wa/zielu1
------------------------------------------
Technical Details
Message-ID:
<34ea8f4a.0@news.tpnet.pl>Path:
mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!news.icm.edu.pl!news.tpnet.pl!ppp-cst6.warszawa.tpnet.plShow Full Headers
Complete Article Headers
From: "Marcin Zielinski" <zielu1@friko3.onet.pl> Newsgroups: pl.comp.lang.c Subject: Edytor tekstu Date: Wed, 18 Feb 1998 08:33:18 +0100 Lines: 139 X-Newsreader: Microsoft Outlook Express 4.71.1712.3 X-MimeOLE: Produced By Microsoft MimeOLE V4.71.1712.3 NNTP-Posting-Host: ppp-cst6.warszawa.tpnet.pl Message-ID: <34ea8f4a.0@news.tpnet.pl> Path: mbox-mo1.pugleaf.net!news-archive.icm.edu.pl!pingwin.icm.edu.pl!news.icm.edu.pl!news.tpnet.pl!ppp-cst6.warszawa.tpnet.pl MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit