Написание текстового редактора с подсветкой синтаксиса

 

Содержание


Введение

1. Файл конфигурации

1.1 Формат файла конфигурации

1.2 Формат файла проверки

2. Разработка программы

2.1 Загрузка файла конфигурации

2.2 Разбор текста и применение к нему стилей

3. Тестовый пример

Заключение

Список литературы

Приложения


Введение


Данная программа является текстовым редактором с подсветкой синтаксиса языков программирования. Настройки для подсветки синтаксиса и некоторые конструкции языка загружаются из XML файла. Это обеспечивает простоту конфигурирования под другие языки программирования. Изначально, программа сконфигурирована под С++.

Для контроля ошибок в XML файле конфигурации используется XML Schema. Для работы с XML используется библиотека LibXML2, она же осуществляет контроль файла настроек при помощи схемы.

Для разбора вводимого текста используется параллельный буфер, в одном хранится форматированный текст, в другом изменённые данные. Поиск конструкций языка в буфере осуществляется стандартным набором функций С++.

1. Файл конфигурации


1.1 Формат файла конфигурации


Файл конфигурации представляет собой XML - файл, в котором хранятся данные, необходимые для подсветки синтаксиса. Файл состоит из корневого элемента language, который в свою очередь содержит 3 дочерних элемента: style, keywords и types.

Элемент style содержит 7 пустых дочерних элементов entry вида

<entry name="entry_name" color="FL_COLOR" font="FL_FONT"/> и имеет 3 атрибута: name, color и font. Один элемент enty описывает одно правило подсветки синтаксиса. Например, элемент вида <entry name="Line Comments" color="FL_DARK_GREEN" font="FL_HELVETICA_ITALIC"/> описывает правило для подсветки строковых комментариев, для которых будет использоваться тёмно-зелёный цвет шрифта и шрифт HELVETICA в курсивном начертании.

Атрибут name элемента entry используется для задания имени правилу подсветки. По этому атрибуту данные для подсветки синтаксиса загружаются в текстовый редактор. Он может принимать следующие значения: Plain (обычный текст), Line Comments (строковые комментарии), Block Comments (многостроковые комментарии), Strings (строки), Directives (директивы), Types (типы), Keywords (ключевые слова).

Атрибут color задаёт цвет, которым будут раскрашены конструкции языка, подходящие под данное правило. Может принимать следующие значения: FL_BLACK, FL_GREEN, FL_DARK_GREEN, FL_BLUE, FL_DARK_BLUE, FL_RED, FL_DARK_RED, FL_MAGENTA, FL_DARK_MAGENTA, FL_CYAN, FL_DARK_CYAN, FL_YELLOW, FL_DARK_YELLOW.

Атрибут font задаёт шрифт, который будет использоваться для конструкций языка, подходящих под данное правило. Может принимать следующие значения: FL_COURIER, FL_COURIER_BOLD, FL_COURIER_ITALIC, FL_COURIER_BOLD_ITALIC, FL_HELVETICA, FL_HELVETICA_BOLD, FL_HELVETICA_ITALIC, FL_HELVETICA_BOLD_ITALIC, FL_TIMES, FL_TIMES_BOLD, FL_TIMES_ITALIC, FL_TIMES_BOLD_ITALIC, FL_SCREEN, FL_SCREEN_BOLD.

Элемент keywords содержит дочерние элементы вида <keyword>keyword_name</keyword>, описывающие ключевые слова языка.

Элемент types содержит дочерние элементы вида <type>type_name</type>, описывающие типы, используемые в языке.


1.2 Формат файла проверки


Во время загрузки файла конфигурации производится его проверка при помощи XML Schema. XML Schema загружается из файла schema. xsd. Она определяет тип данных, использующиеся в атрибутах свойств и элементов, последовательность элементов и их количество, допустимые значения для перечислений.

Перечисление определяется следующим образом:

<xs: attribute name="name" use="required">

<xs: simpleType>

<xs: restriction base="xs: string">

<xs: enumeration value="Plain"/>

<xs: enumeration value="Line Comments"/>

<xs: enumeration value="Block Comments"/>

<xs: enumeration value="Strings"/>

<xs: enumeration value="Directives"/>

<xs: enumeration value="Types"/>

<xs: enumeration value="Keywords"/>

</xs: restriction>

</xs: simpleType>

</xs: attribute>

Здесь аттрибут name определён как обязательный (use="required"), значение может быть только текстовым (base="xs: string") и может быть одним из значений аттрибута value элемента xs: enumeration.

Корневой элемент language должен содержать 3 дочерних элемента: style, keywords и types. На языке XML Schema это правило записывается так:

<xs: element name="language">

<xs: complexType>

<xs: sequence>

<xs: element ref="style"/>

<xs: element ref="keywords"/>

<xs: element ref="types"/>

</xs: sequence>

<xs: attribute name="name" use="required" type="xs: string" fixed="C++"/>

</xs: complexType>

</xs: element>

Элемент types может содержать 1 или более дочерних элементов type, значения которых должны быть строкового типа. Данное правило реализуется при помощи следующей конструкции:

<xs: element name="types">

<xs: complexType>

<xs: sequence>

<xs: element ref="type" minOccurs="1" maxOccurs="unbounded"/>

</xs: sequence>

</xs: complexType>

</xs: element>

<xs: element name="type" type="xs: string"/>

Элемент style содержит 7 дочерних элементов entry, содержащих данные сложного типа. Правило для данного утверждения выглядит следующим образом:

<xs: element name="style">

<xs: complexType>

<xs: sequence>

<xs: element ref="entry" minOccurs="7" maxOccurs="7"/>

</xs: sequence>

</xs: complexType>

</xs: element>

текстовый редактор подсветка синтаксис

2. Разработка программы


2.1 Загрузка файла конфигурации


Для начала создадим 3 переменных типа xmlChar:

xmlChar *uri; // используется для хранения атрибутов

xmlChar *color; // используется для хранения значения цвета

xmlChar *font; // используется для хранения значения шрифта

Загрузка данных из XML файла происходит в функции loadHighlightingData ():

void loadHighlightingData ()

{doc1;char * filename = "config. xml";= xmlReadFile (filename, NULL, XML_PARSE_NONET);(is_valid (doc1, "schema. xsd") == 1)

{i = 0;xmldoc = NULL;*uri;( (xmldoc = xmlReadFile (filename, NULL, 0)) == NULL) return;cur = xmlDocGetRootElement (xmldoc);(xmldoc, "style", "entry");(xmldoc, "keywords", "keyword");(xmldoc, "types", "type");(uri);(color);(font);

}else

{

// Ошибка в XMLXMLError;= xmlGetLastError ();_alert (XMLError->message);

}

}

Сначала мы создаём указатель на XML документ командой xmlDocPtr doc1;, присваиваем имя загружаемого файла переменной filename. Затем считываем файл и проверяем его при помощи XML Schema. Проверку осуществляет функция is_valid (const xmlDocPtr doc, const char *schema_filename), получающая в качестве аргументов указатель на XML документ и имя файла XML Schema. В данной функции сначала загружается файл схемы:schema_doc = xmlReadFile (schema_filename, NULL, XML_PARSE_NONET);

if (schema_doc == NULL) {_alert ("The schema cannot be loaded or is not well-formed");

return - 1;

}

В случае невозможности загрузить файл выводится соответствующее сообщение при помощи функции fl_alert ();

Далее создаётся указательна контекст парсера схемы, и также выводится сообщение о ошибке при невозможности его создания:

xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt (schema_doc);

if (parser_ctxt == NULL) {_alert ("Unable to create a parser context for the schema", "Ok"); (schema_doc);

return - 2;

}

Затем сама схема проверяется на корректность и также выдаётся сообщение о ошибке при нахождении ошибок в схеме:

xmlSchemaPtr schema = xmlSchemaParse (parser_ctxt);

if (schema == NULL) {_alert ("the schema itself is not valid", "Ok");(parser_ctxt);(schema_doc);

return - 3;

}

После этого создаётся контекст проверки:valid_ctxt = xmlSchemaNewValidCtxt (schema);

if (valid_ctxt == NULL) {_alert ("unable to create a validation context for the schema", "Ok");(schema);(parser_ctxt);

xmlFreeDoc (schema_doc);- 4;

}

И наконец, происходит проверка XML документа:

int is_valid = (xmlSchemaValidateDoc (valid_ctxt, doc) == 0);(valid_ctxt);(schema);(parser_ctxt);(schema_doc);

return is_valid? 1: 0;

В случае, если загружаемый XML документ имеет ошибки, то выполняется следующий код:

xmlErrorPtr XMLError;

XMLError = xmlGetLastError ();

fl_alert (XMLError->message);

Здесь мы создаём указатель указатель на структуру XMLError, заносим в эту структуру сведения о последней ошибке, и затем выдаём сообщение о ошибке при помощи функции fl_allert ();.

Если проверка XML файла прошла успешно, то выполняется следующий код:

xmlDocPtr xmldoc = NULL;( (xmldoc = xmlReadFile (filename, NULL, 0)) == NULL) return;cur = xmlDocGetRootElement (xmldoc);(xmldoc, "style", "entry");(xmldoc, "keywords", "keyword");(xmldoc, "types", "type");(uri);(color);(font);

Здесь мы создаём указатель на XML документ, загружаем его из файла, получаем указатель на корневой элемент документа и заполняем таблицу стилей данными из XML документа при помощи функции parseXMLDoc (xmlDocPtr doc, char *nodeName, char *curNode). Эта функция вызывается 3 раза: для чтения данных подсветки, для получения списка ключевых слов и списка типов. Рассмотрим эту функцию подробнее:parseXMLDoc (xmlDocPtr doc, char *nodeName, char *curNode)

{cur;= xmlDocGetRootElement (doc);

cur = cur->xmlChildrenNode;(cur! = NULL)

{( (! xmlStrcmp (cur->name, (const xmlChar *) nodeName)))

{(doc, cur, curNode);

}= cur->next;

}

}

Сначала создаётся указатель на элемент документа и ему присваивается значение корневого элемента. Затем устанавливается режим дочерних элементов и в цикле осуществляется поиск элемента, заданного вторым параметром функции. При его нахождении выполняется функция parseNodes (xmlDocPtr doc, xmlNodePtr cur, char *curNode), которая и производит загрузку значений в таблицы стилей, ключевых слов и типов. Данная функция реализована следующим образом:parseNodes (xmlDocPtr doc, xmlNodePtr cur, char *curNode)

{*key;exit (0);= cur->xmlChildrenNode;(cur! = NULL)

{( (! xmlStrcmp (cur->name, (const xmlChar *) curNode)))

{( (! xmlStrcmp (cur->name, (const xmlChar *)"entry")))

{(doc, cur, "Plain");(doc, cur, "Line Comments");(doc, cur, "Block Comments");(doc, cur, "Strings");(doc, cur, "Directives");(doc, cur, "Types");(doc, cur, "Keywords");;

}else

{= xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);(strcmp (curNode, "type") == 0)

{_types. push_back ( (const char *) key);

}else

{_keywords. push_back ( (const char *) key);

}(key);

}

}= cur->next;

};

}

Данная функция состоит из 2 частей: первая часть предназначена для загрузки таблицы стилей, вторая для загрузки ключевых слов и типов. Загрузка стилей осуществляется функцией parseStyles (xmlDocPtr doc, xmlNodePtr cur, const char *name), в которой все 7 элементов описаны следующим образом:

if ( (! xmlStrcmp (uri, (const xmlChar *)"Plain")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[0] = stylebuftemp;

}

Функции XMLValue2FLfont (const xmlChar* XMLvalue) и XMLValue2FLColor (const xmlChar* XMLvalue) получают указатель на строку и проверяют, является ли она значением FLCOLOR или FLFONT следующим образом:( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_BLACK")))

{FL_BLACK;

}

или( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_COURIER")))

{FL_COURIER;

}

Если функция parseNodes получает указатель на элемент, содержащий значения ключевых слов, то они загружаются в массив следующим образом:

code_keywords. push_back ( (const char *) key). Таким же образом загружаются и типы: code_types. push_back ( (const char *) key).


2.2 Разбор текста и применение к нему стилей


FL_Text_Editor виджет поддерживает подсветку синтаксиса различными цветами, шрифтами и размером шрифта. Данный класс основан на ядре текстового редактора NEdit, который поддерживает параллельный стилевой буфер, который содержит информацию о цвете, шрифте и размере текста, который отображается.

Для хранения стилей используется структура Fl_Text_Display:: Style_Table_Entry, определённая в файле Fl_Text_Display. H:Style_Table_Entry

{_Colorcolor;_Fontfont;;;

}задаёт цвет для текста, font задаёт индекс FLTK шрифта, size задаёт размер шрифта в пикселях. attr не используется.

Все семь стилей ассоциированы с латинскими буквами - A (обычный текст), B (строковый комментарий), C (блоковый комментарий), D (строки), E (директивы), F (типы), G (ключевые слова).

Каждый стиль в стилевом буфере описывается символом, начинающимся с 'A'.

Чтобы ассоциировать стилевую информацию и буфер с виджетом текстового редактора, нужно вызвать функцию highlight_data ():

Fl_Text_Buffer * stylebuf;>editor->highlight_data (stylebuf, styletable,(styletable) /sizeof (styletable [0])

A, style_unfinished_cb, 0);

Затем мы добавляем callback к главному текстовому буферу, таким образом, изменения в текстовом буфере будут отображаться в стилевом буфере:

textbuf->add_modify_callback (style_update, w->editor);

Функция style_update () вызывается когда текст добавлен или удалён из текстового буфера. Она отображает изменения в стилевом буфере и затем обновляет стилевую информацию.

Функция style_parse () сканирует копию текста в буфере и генерирует необходимые стилевые символы для отображения стиля. Разбор начинается с начала строки.

3. Тестовый пример


На рисунке 1 показано главное окно программы с загруженным текстом на языке С++.


Рисунок 1.


На рисунке 2 показано сообщение о ошибке при загрузке файла настроек.


Рисунок 2.


На рисунке 3 показано сообщение о ошибке при загрузке файла схемы.


Рисунок 3.

Заключение


В данном курсовом проекте был разработан текстовый редактор с подсветкой синтаксиса языков программирования с возможностью конфигурирования настроек подсветки синтаксиса и определением типов и ключевых слов языка. Данная программа является кроссплатформенной, т.к. она написана с применением кроссплатформенных библиотек FLTK 1.3.0 и LibXML2.

Список литературы


1. #"center">Приложения


Приложение 1


<? xml version="1.0" encoding="UTF-8"? >

<language name="C++" xmlns: xsi="#"justify"><style>

<entry name="Plain" color="FL_BLACK" font="FL_COURIER"/>

<entry name="Line Comments" color="FL_DARK_GREEN" font="FL_HELVETICA_ITALIC"/>

<entry name="Block Comments" color="FL_DARK_GREEN" font="FL_HELVETICA_ITALIC"/>

<entry name="Strings" color="FL_BLUE" font="FL_COURIER"/>

<entry name="Directives" color="FL_DARK_YELLOW" font="FL_TIMES_BOLD"/>

<entry name="Types" color="FL_DARK_RED" font="FL_COURIER_BOLD"/>

<entry name="Keywords" color="FL_BLUE" font="FL_COURIER_BOLD"/>

</style>

<keywords>

<keyword>and</keyword>

<keyword>and_eq</keyword>

<keyword>asm</keyword>

<keyword>bitand</keyword>

<keyword>bitor</keyword>

<keyword>break</keyword>

<keyword>case</keyword>

<keyword>catch</keyword>

<keyword>compl</keyword>

<keyword>continue</keyword>

<keyword>default</keyword>

<keyword>delete</keyword>

<keyword>do</keyword>

<keyword>else</keyword>

<keyword>false</keyword>

<keyword>for</keyword>

<keyword>goto</keyword>

<keyword>if</keyword>

<keyword>new</keyword>

<keyword>not</keyword>

<keyword>not_eq</keyword>

<keyword>operator</keyword>

<keyword>or</keyword>

<keyword>or_eq</keyword>

<keyword>return</keyword>

<keyword>switch</keyword>

<keyword>template</keyword>

<keyword>this</keyword>

<keyword>throw</keyword>

<keyword>true</keyword>

<keyword>try</keyword>

<keyword>while</keyword>

<keyword>xor</keyword>

<keyword>xor_eq</keyword>

</keywords>

<types>

<type>auto</type>

<type>bool</type>

<type>char</type>

<type>class</type>

<type>const</type>

<type>const_cast</type>

<type>double</type>

<type>dynamic_cast</type>

<type>enum</type>

<type>explicit</type>

<type>extern</type>

<type>float</type>

<type>friend</type>

<type>inline</type>

<type>int</type>

<type>long</type>

<type>mutable</type>

<type>namespace</type>

<type>private</type>

<type>protected</type>

<type>public</type>

<type>register</type>

<type>short</type>

<type>signed</type>

<type>sizeof</type>

<type>static</type>

<type>static_cast</type>

<type>struct</type>

<type>template</type>

<type>typedef</type>

<type>typename</type>

<type>union</type>

<type>unsigned</type>

<type>virtual</type>

<type>void</type>

<type>volatile</type>

</types>

</language>

Приложение 2


<? xml version="1.0" encoding="UTF-8"? >

<xs: schema xmlns: xs="#"justify"><xs: element name="types">

<xs: complexType>

<xs: sequence>

<xs: element ref="type" minOccurs="1" maxOccurs="unbounded"/>

</xs: sequence>

</xs: complexType>

</xs: element>

<xs: element name="type" type="xs: string"/>

<xs: element name="style">

<xs: complexType>

<xs: sequence>

<xs: element ref="entry" minOccurs="7" maxOccurs="7"/>

</xs: sequence>

</xs: complexType>

</xs: element>

<xs: element name="language">

<xs: complexType>

<xs: sequence>

<xs: element ref="style"/>

<xs: element ref="keywords"/>

<xs: element ref="types"/>

</xs: sequence>

<xs: attribute name="name" use="required" type="xs: string" fixed="C++"/>

</xs: complexType>

</xs: element>

<xs: element name="keywords">

<xs: complexType>

<xs: sequence>

<xs: element ref="keyword" minOccurs="1" maxOccurs="unbounded"/>

</xs: sequence>

</xs: complexType>

</xs: element>

<xs: element name="keyword" type="xs: string">

</xs: element>

<xs: element name="entry">

<xs: complexType>

<xs: attribute name="name" use="required">

<xs: simpleType>

<xs: restriction base="xs: string">

<xs: enumeration value="Plain"/>

<xs: enumeration value="Line Comments"/>

<xs: enumeration value="Block Comments"/>

<xs: enumeration value="Strings"/>

<xs: enumeration value="Directives"/>

<xs: enumeration value="Types"/>

<xs: enumeration value="Keywords"/>

</xs: restriction>

</xs: simpleType>

</xs: attribute>

<xs: attribute name="font" use="required">

<xs: simpleType>

<xs: restriction base="xs: string">

<xs: enumeration value="FL_COURIER"/>

<xs: enumeration value="FL_COURIER_BOLD"/>

<xs: enumeration value="FL_HELVETICA_ITALIC"/>

<xs: enumeration value="FL_TIMES_BOLD"/>

</xs: restriction>

</xs: simpleType>

</xs: attribute>

<xs: attribute name="color" use="required">

<xs: simpleType>

<xs: restriction base="xs: string">

<xs: enumeration value="FL_BLACK"/>

<xs: enumeration value="FL_BLUE"/>

<xs: enumeration value="FL_DARK_GREEN"/>

<xs: enumeration value="FL_DARK_RED"/>

<xs: enumeration value="FL_DARK_YELLOW"/>

</xs: restriction>

</xs: simpleType>

</xs: attribute>

</xs: complexType>

</xs: element>

</xs: schema>

Приложение 3


#include <string>

#include <vector>

#include <algorithm>

#ifdef __MWERKS__

# define FL_DLL

#endif

#include <FL/Fl. H>

#include <FL/Fl_Group. H>

#include <FL/Fl_Double_Window. H>

#include <FL/fl_ask. H>

#include <FL/Fl_Native_File_Chooser. H>

#include <FL/Fl_Menu_Bar. H>

#include <FL/Fl_Input. H>

#include <FL/Fl_Button. H>

#include <FL/Fl_Return_Button. H>

#include <FL/Fl_Text_Buffer. H>

#include <FL/Fl_Text_Editor. H>

#include <FL/filename. H>

#include <libxml/parser. h>

#include <libxml/tree. h>

#include <libxml/xmlschemas. h>

#include <libxml/xmlerror. h>namespace std;changed = 0;filename [FL_PATH_MAX] = "";title [FL_PATH_MAX];_Text_Buffer *textbuf = 0;

// Syntax highlighting stuff.

#define TS 14 // default editor textsize_Text_Buffer *stylebuf = 0;_Text_Display:: Style_Table_Entry styletable [7]; // Style table:: vector <std:: string> code_keywords;:: vector <std:: string> code_types;:: vector <std:: string>:: iterator it;:: vector <std:: string>:: iterator it1;*uri;*color;*font;i (0);_Text_Display:: Style_Table_Entry stylebuftemp;is_valid (const xmlDocPtr doc, const char *schema_filename)

{schema_doc = xmlReadFile (schema_filename, NULL, XML_PARSE_NONET);(schema_doc == NULL) {_alert ("The schema cannot be loaded or is not well-formed");- 1;

}parser_ctxt = xmlSchemaNewDocParserCtxt (schema_doc);(parser_ctxt == NULL) {_alert ("Unable to create a parser context for the schema", "Ok");(schema_doc);- 2;

}schema = xmlSchemaParse (parser_ctxt);(schema == NULL) {_alert ("the schema itself is not valid", "Ok");(parser_ctxt);(schema_doc);- 3;

}valid_ctxt = xmlSchemaNewValidCtxt (schema);(valid_ctxt == NULL) {_alert ("unable to create a validation context for the schema", "Ok");(schema);(parser_ctxt);(schema_doc);- 4;

}is_valid = (xmlSchemaValidateDoc (valid_ctxt, doc) == 0);(valid_ctxt);(schema);(parser_ctxt);(schema_doc);is_valid? 1: 0;

}int XMLValue2FLColor (const xmlChar* XMLvalue)

{( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_BLACK")))

{FL_BLACK;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_GREEN")))

{FL_GREEN;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_DARK_GREEN")))

{FL_DARK_GREEN;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_BLUE")))

{FL_BLUE;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_DARK_BLUE")))

{FL_DARK_BLUE;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_RED")))

{FL_RED;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_DARK_RED")))

{FL_DARK_RED;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_MAGENTA")))

{FL_MAGENTA;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_DARK_MAGENTA")))

{FL_DARK_MAGENTA;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_CYAN")))

{FL_CYAN;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_DARK_CYAN")))

{FL_DARK_CYAN;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_YELLOW")))

{FL_YELLOW;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_DARK_YELLOW")))

{FL_DARK_YELLOW;

}

}XMLValue2FLfont (const xmlChar* XMLvalue)

{( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_COURIER")))

{FL_COURIER;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_COURIER_BOLD")))

{FL_COURIER_BOLD;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_COURIER_ITALIC")))

{FL_COURIER_ITALIC;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_COURIER_BOLD_ITALIC")))

{FL_COURIER_BOLD_ITALIC;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_HELVETICA")))

{FL_HELVETICA;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_HELVETICA_BOLD")))

{FL_HELVETICA_BOLD;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_HELVETICA_ITALIC")))

{FL_HELVETICA_ITALIC;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_HELVETICA_BOLD_ITALIC")))

{FL_HELVETICA_BOLD_ITALIC;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_TIMES")))

{FL_TIMES;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_TIMES_BOLD")))

{FL_TIMES_BOLD;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_TIMES_ITALIC")))

{FL_TIMES_ITALIC;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_TIMES_BOLD_ITALIC")))

{FL_TIMES_BOLD_ITALIC;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_SCREEN")))

{FL_SCREEN;

}( (! xmlStrcmp (XMLvalue, (const xmlChar *)"FL_SCREEN_BOLD")))

{FL_SCREEN_BOLD;

}

}parseStyles (xmlDocPtr doc, xmlNodePtr cur, const char *name)

{(cur! = NULL)

{= xmlGetProp (cur, (const xmlChar *)"name");( (! xmlStrcmp (uri, (const xmlChar *)"Plain")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[0] = stylebuftemp;

}( (! xmlStrcmp (uri, (const xmlChar *)"Line Comments")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[1] = stylebuftemp;

}( (! xmlStrcmp (uri, (const xmlChar *)"Block Comments")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[2] = stylebuftemp;

}( (! xmlStrcmp (uri, (const xmlChar *)"Strings")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[3] = stylebuftemp;

}( (! xmlStrcmp (uri, (const xmlChar *)"Directives")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[4] = stylebuftemp;

}( (! xmlStrcmp (uri, (const xmlChar *)"Types")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[5] = stylebuftemp;

}( (! xmlStrcmp (uri, (const xmlChar *)"Keywords")))

{= xmlGetProp (cur, (const xmlChar *)"color");= xmlGetProp (cur, (const xmlChar *)"font");. color = XMLValue2FLColor (color);. font = XMLValue2FLfont (font);. size = TS;[6] = stylebuftemp;

}= cur->next;

}

}parseNodes (xmlDocPtr doc, xmlNodePtr cur, char *curNode)

{*key;exit (0);= cur->xmlChildrenNode;(cur! = NULL)

{( (! xmlStrcmp (cur->name, (const xmlChar *) curNode)))

{( (! xmlStrcmp (cur->name, (const xmlChar *)"entry")))

{(doc, cur, "Plain");(doc, cur, "Line Comments");(doc, cur, "Block Comments");(doc, cur, "Strings");(doc, cur, "Directives");(doc, cur, "Types");(doc, cur, "Keywords");;

}else

{= xmlNodeListGetString (doc, cur->xmlChildrenNode, 1);(strcmp (curNode, "type") == 0)

{_types. push_back ( (const char *) key);

}else

{_keywords. push_back ( (const char *) key);

}(key);

}

}= cur->next;

};

}parseXMLDoc (xmlDocPtr doc, char *nodeName, char *curNode)

{cur;= xmlDocGetRootElement (doc);= cur->xmlChildrenNode;(cur! = NULL)

{( (! xmlStrcmp (cur->name, (const xmlChar *) nodeName)))

{(doc, cur, curNode);

}= cur->next;

}

}loadHighlightingData ()

{doc1;char * filename = "config. xml";= xmlReadFile (filename, NULL, XML_PARSE_NONET);(is_valid (doc1, "schema. xsd") == 1)

{i = 0;xmldoc = NULL;*uri;( (xmldoc = xmlReadFile (filename, NULL, 0)) == NULL) return;cur = xmlDocGetRootElement (xmldoc);(xmldoc, "style", "entry");(xmldoc, "keywords", "keyword");(xmldoc, "types", "type");(uri);(color);(font);

}else

{

// error in XMLXMLError;= xmlGetLastError ();_alert (XMLError->message);

}

}

//

// 'style_parse () ' - Parse text and produce style data.

// _parse (const char *text,*style,length) {current;col;last;buf [255],

*bufptr;char *temp;

// Style letters:

//

// A - Plain

// B - Line comments

// C - Block comments

// D - Strings

// E - Directives

// F - Types

// G - Keywords(current = *style, col = 0, last = 0; length > 0; length - -, text ++) {(current == 'B' || current == 'F' || current == 'G') current = 'A';(current == 'A') {

// Check for directives, comments, strings, and keywords.(col == 0 && *text == '#') {

// Set style to directive= 'E';

} else if (strncmp (text, " // ",

) == 0) {= 'B';(; length > 0 && *text! = '\n'; length - -, text ++) *style++ = 'B';(length == 0) break;

} else if (strncmp (text, "/*",

) == 0) {= 'C';

} else if (strncmp (text, "\\",

) == 0) {

// Quoted quote.

*style++ = current;

*style++ = current;++;- -;+= 2;;

} else if (*text == '') {= 'D';

} else if (! last && (islower ( (*text) &255) || *text == '_')) {

// Might be a keyword.(temp = text, bufptr = buf;

(islower ( (*temp) &255) || *temp == '_') && bufptr < (buf + sizeof (buf) - 1);

*bufptr++ = *temp++);(! islower ( (*temp) &255) && *temp! = '_') {

*bufptr = '\0';= buf;= find (code_types. begin (), code_types. end (), bufptr);= find (code_keywords. begin (), code_keywords. end (), bufptr);(it! = code_types. end ())

{(text < temp) {

*style++ = 'F';++;- -;++;

}- -;++;= 1;;

} else if (it1! = code_keywords. end ())

{(text < temp) {

*style++ = 'G';++;- -;++;

}- -;++;= 1;;

}

}

}

} else if (current == 'C' && strncmp (text, "*/",

) == 0) {

// Close a C comment.

*style++ = current;

*style++ = current;++;- -;= 'A';+= 2;;

} else if (current == 'D') {

// Continuing in string.(strncmp (text, "\\",

) == 0) {

// Quoted end quote.

*style++ = current;

*style++ = current;++;- -;+= 2;;

} else if (*text == '') {

// End quote.

*style++ = current;++;= 'A';;

}

}

// Copy style info.(current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G';*style++ = current;++;= isalnum ( (*text) &255) || *text == '_' || *text == '. ';(*text == '\n') {

// Reset column and possibly reset the style= 0;(current == 'B' || current == 'E') current = 'A';

}

}

}

//

// 'style_init () ' - Initialize the style buffer.

// _init (void) {*style = new char [textbuf->length () + 1];*text = textbuf->text ();(style, 'A', textbuf->length ());[textbuf->length ()] = '\0';(! stylebuf) stylebuf = new Fl_Text_Buffer (textbuf->length ());_parse (text, style, textbuf->length ());>text (style);[] style;(text);

}

//

// 'style_unfinished_cb () ' - Update unfinished styles.

// _unfinished_cb (int, void*) {

}

//

// 'style_update () ' - Update the style buffer.

// _update (int pos, // I - Position of updatenInserted, // I - Number of inserted charsnDeleted, // I - Number of deleted chars/*nRestyled*/, // I - Number of restyled charschar * /*deletedText*/, // I - Text that was deleted*cbArg) { // I - Callback data, // Start of text; // End of text, // Last style on line

*style, // Style data

*text; // Text data

// If this is just a selection change, just unselect the style buffer.(nInserted == 0 && nDeleted == 0) {>unselect ();;

}

// Track changes in the text buffer.(nInserted > 0) {

// Insert characters into the style buffer.= new char [nInserted + 1];(style, 'A', nInserted);[nInserted] = '\0';>replace (pos, pos + nDeleted, style);[] style;

} else {

// Just delete characters in the style buffer.>remove (pos, pos + nDeleted);

}

// Select the area that was just updated to avoid unnecessary

// callbacks.>select (pos, pos + nInserted - nDeleted);

// Re-parse the changed region; we do this by parsing from the

// beginning of the previous line of the changed region to the end of

// the line of the changed region. Then we check the last

// style character and keep updating if we have a multi-line

// comment character.= textbuf->line_start (pos);

// if (start > 0) start = textbuf->line_start (start - 1);= textbuf->line_end (pos + nInserted);= textbuf->text_range (start, end);= stylebuf->text_range (start, end);(start==end)= 0;= style [end - start - 1];

// printf ("start = %d, end = %d, text = %s, style = %s, last='%c'. \n",

// start, end, text, style, last);_parse (text, style, end - start);

// printf ("new style = %s, new last='%c'. \n",

// style, style [end - start - 1]);>replace (start, end, style);

( (Fl_Text_Editor *) cbArg) - >redisplay_range (start, end);(start==end || last! = style [end - start - 1]) {

// printf ("Recalculate the rest of the buffer style\n");

// Either the user deleted some text, or the last character

// on the line changed styles, so reparse the

// remainder of the buffer.(text);(style);= textbuf->length ();= textbuf->text_range (start, end);= stylebuf->text_range (start, end);_parse (text, style, end - start);>replace (start, end, style);

( (Fl_Text_Editor *) cbArg) - >redisplay_range (start, end);

}(text);(style);

}

// Editor window functions and class.save_cb ();saveas_cb ();find2_cb (Fl_Widget*, void*);replall_cb (Fl_Widget*, void*);replace2_cb (Fl_Widget*, void*);replcan_cb (Fl_Widget*, void*);EditorWindow: public Fl_Double_Window {:(int w, int h, const char* t);

~EditorWindow ();_Window *replace_dlg;_Input *replace_find;_Input *replace_with;_Button *replace_all;_Return_Button *replace_next;_Button *replace_cancel;_Text_Editor *editor;search [256];

};:: EditorWindow (int w, int h, const char* t): Fl_Double_Window (w, h, t) {_dlg = new Fl_Window (300, 105, "Replace");_find = new Fl_Input (80, 10, 210, 25, "Find: ");_find->align (FL_ALIGN_LEFT);_with = new Fl_Input (80, 40, 210, 25, "Replace: ");_with->align (FL_ALIGN_LEFT);_all = new Fl_Button (10, 70, 90, 25, "Replace All");_all->callback ( (Fl_Callback *) replall_cb, this);_next = new Fl_Return_Button (105, 70, 120, 25, "Replace Next");_next->callback ( (Fl_Callback *) replace2_cb, this);_cancel = new Fl_Button (230, 70, 60, 25, "Cancel");_cancel->callback ( (Fl_Callback *) replcan_cb, this);_dlg->end ();_dlg->set_non_modal ();= 0;

*search = (char) 0;();

}:: ~EditorWindow () {replace_dlg;

}check_save (void) {(! changed) return 1;r = fl_choice ("The current file has not been saved. \n"

"Would you like to save it now?",

"Cancel", "Save", "Don't Save");(r == 1) {_cb (); // Save the file.! changed;

}(r == 2)? 1: 0;

}loading = 0;load_file (const char *newfile, int ipos) {= 1;insert = (ipos! = - 1);= insert;(! insert) strcpy (filename, "");r;(! insert) r = textbuf->loadfile (newfile);r = textbuf->insertfile (newfile, ipos);

// changed = changed || textbuf->input_file_was_transcoded;(r)_alert ("Error reading from file \'%s\': \n%s.", newfile, strerror (errno));(! insert) strcpy (filename, newfile);= 0;>call_modify_callbacks ();

}save_file (const char *newfile) {(textbuf->savefile (newfile))_alert ("Error writing to file \'%s\': \n%s.", newfile, strerror (errno));(filename, newfile);= 0;>call_modify_callbacks ();

}copy_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;_Text_Editor:: kf_copy (0, e->editor);

}cut_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;_Text_Editor:: kf_cut (0, e->editor);

}delete_cb (Fl_Widget*, void*) {>remove_selection ();

}find_cb (Fl_Widget* w, void* v) {* e = (EditorWindow*) v;char *val;= fl_input ("Search String:", e->search);(val! = NULL) {

// User entered a string - go find it!(e->search, val);_cb (w, v);

}

}find2_cb (Fl_Widget* w, void* v) {* e = (EditorWindow*) v;(e->search [0] == '\0') {

// Search string is blank; get a new one._cb (w, v);;

}pos = e->editor->insert_position ();found = textbuf->search_forward (pos, e->search, &pos);(found) {

// Found a match; select and update the position.>select (pos, pos+strlen (e->search));>editor->insert_position (pos+strlen (e->search));>editor->show_insert_position ();

}fl_alert ("No occurrences of \'%s\' found!", e->search);

}set_title (Fl_Window* w) {(filename [0] == '\0') strcpy (title, "Untitled");{*slash;= strrchr (filename, '/');

#ifdef WIN32(slash == NULL) slash = strrchr (filename, '\\');

#endif(slash! = NULL) strcpy (title, slash + 1);strcpy (title, filename);

}(changed) strcat (title, " (modified)");>label (title);

}changed_cb (int, int nInserted, int nDeleted, int, const char*, void* v) {( (nInserted || nDeleted) &&! loading) changed = 1;*w = (EditorWindow *) v;_title (w);(loading) w->editor->show_insert_position ();

}new_cb (Fl_Widget*, void*) {(! check_save ()) return;[0] = '\0';>select (0, textbuf->length ());>remove_selection ();= 0;>call_modify_callbacks ();

}open_cb (Fl_Widget*, void*) {(! check_save ()) return;_Native_File_Chooser fnfc;. title ("Open file");. type (Fl_Native_File_Chooser:: BROWSE_FILE);(fnfc. show ()) return;_file (fnfc. filename (), - 1);

}insert_cb (Fl_Widget*, void *v) {_Native_File_Chooser fnfc;. title ("Insert file");. type (Fl_Native_File_Chooser:: BROWSE_FILE);(fnfc. show ()) return;*w = (EditorWindow *) v;_file (fnfc. filename (), w->editor->insert_position ());

}paste_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;_Text_Editor:: kf_paste (0, e->editor);

}num_windows = 0;close_cb (Fl_Widget*, void* v) {* w = (EditorWindow*) v;(num_windows == 1) {(! check_save ());

}>hide ();>editor->buffer (0);>remove_modify_callback (style_update, w->editor);>remove_modify_callback (changed_cb, w);:: delete_widget (w);_windows--;(! num_windows) exit (0);

}quit_cb (Fl_Widget*, void*) {(changed &&! check_save ());(0);

}replace_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;>replace_dlg->show ();

}replace2_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;char *find = e->replace_find->value ();char *replace = e->replace_with->value ();(find [0] == '\0') {

// Search string is blank; get a new one.>replace_dlg->show ();;

}>replace_dlg->hide ();pos = e->editor->insert_position ();found = textbuf->search_forward (pos, find, &pos);(found) {

// Found a match; update the position and replace text.>select (pos, pos+strlen (find));>remove_selection ();>insert (pos, replace);>select (pos, pos+strlen (replace));>editor->insert_position (pos+strlen (replace));>editor->show_insert_position ();

}fl_alert ("No occurrences of \'%s\' found!", find);

}replall_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;char *find = e->replace_find->value ();char *replace = e->replace_with->value ();= e->replace_find->value ();(find [0] == '\0') {

// Search string is blank; get a new one.>replace_dlg->show ();;

}>replace_dlg->hide ();>editor->insert_position (0);times = 0;

// Loop through the whole string(int found = 1; found;) {pos = e->editor->insert_position ();= textbuf->search_forward (pos, find, &pos);(found) {

// Found a match; update the position and replace text.>select (pos, pos+strlen (find));>remove_selection ();>insert (pos, replace);>editor->insert_position (pos+strlen (replace));>editor->show_insert_position ();++;

}

}(times) fl_message ("Replaced %d occurrences.", times);fl_alert ("No occurrences of \'%s\' found!", find);

}replcan_cb (Fl_Widget*, void* v) {* e = (EditorWindow*) v;>replace_dlg->hide ();

}save_cb () {(filename [0] == '\0') {

// No filename - get one!_cb ();;

}save_file (filename);

}saveas_cb () {_Native_File_Chooser fnfc;. title ("Save File As?");. type (Fl_Native_File_Chooser:: BROWSE_SAVE_FILE);(fnfc. show ()) return;_file (fnfc. filename ());

}_Window* new_view ();view_cb (Fl_Widget*, void*) {_Window* w = new_view ();>show ();

}_Menu_Item menuitems [] = {

{ "&File", 0, 0, 0, FL_SUBMENU },

{ "&New File", 0, (Fl_Callback *) new_cb },

{ "&Open File.", FL_COMMAND + 'o', (Fl_Callback *) open_cb },

{ "&Insert File.", FL_COMMAND + 'i', (Fl_Callback *) insert_cb, 0, FL_MENU_DIVIDER },

{ "&Save File", FL_COMMAND + 's', (Fl_Callback *) save_cb },

{ "Save File &As.", FL_COMMAND + FL_SHIFT + 's', (Fl_Callback *) saveas_cb, 0, FL_MENU_DIVIDER },

{ "New &View", FL_ALT + 'v', (Fl_Callback *) view_cb, 0 },

{ "&Close View", FL_COMMAND + 'w', (Fl_Callback *) close_cb, 0, FL_MENU_DIVIDER },

{ "E&xit", FL_COMMAND + 'q', (Fl_Callback *) quit_cb, 0 },

{ 0 },

{ "&Edit", 0, 0, 0, FL_SUBMENU },

{ "Cu&t", FL_COMMAND + 'x', (Fl_Callback *) cut_cb },

{ "&Copy", FL_COMMAND + 'c', (Fl_Callback *) copy_cb },

{ "&Paste", FL_COMMAND + 'v', (Fl_Callback *) paste_cb },

{ "&Delete", 0, (Fl_Callback *) delete_cb },

{ 0 },

{ "&Search", 0, 0, 0, FL_SUBMENU },

{ "&Find.", FL_COMMAND + 'f', (Fl_Callback *) find_cb },

{ "F&ind Again", FL_COMMAND + 'g', find2_cb },

{ "&Replace.", FL_COMMAND + 'r', replace_cb },

{ "Re&place Again", FL_COMMAND + 't', replace2_cb },

{ 0 },

{ 0 }

};_Window* new_view () {* w = new EditorWindow (660, 400, title);>begin ();_Menu_Bar* m = new Fl_Menu_Bar (0, 0, 660, 30);>copy (menuitems, w);>editor = new Fl_Text_Editor (0, 30, 660, 370);>editor->textfont (FL_COURIER);>editor->textsize (TS);>editor->buffer (textbuf);>editor->highlight_data (stylebuf, styletable,(styletable) / sizeof (styletable [0]),

'A', style_unfinished_cb, 0);>text ();_init ();>end ();>resizable (w->editor);>callback ( (Fl_Callback *) close_cb, w);>add_modify_callback (style_update, w->editor);>add_modify_callback (changed_cb, w);>call_modify_callbacks ();_windows++;w;

}main (int argc, char **argv) {_TEST_VERSION;= new Fl_Text_Buffer;_init ();_Window* window = new_view ();>show (1, argv);(argc > 1) load_file (argv [1], - 1);

return Fl:: run ();

}


Содержание Введение 1. Файл конфигурации 1.1 Формат файла конфигурации 1.2 Формат файла проверки 2. Разработка программы 2.1 Загрузка файл

Больше работ по теме:

КОНТАКТНЫЙ EMAIL: [email protected]

Скачать реферат © 2017 | Пользовательское соглашение

Скачать      Реферат

ПРОФЕССИОНАЛЬНАЯ ПОМОЩЬ СТУДЕНТАМ