Разработка текстового редактора с подсветкой синтаксиса языков программирования

Формат файла конфигурации, содержащего данные для подсветки синтаксиса. Его проверка при помощи XML Schema. Реализация функций для чтения данных подсветки и по загрузке таблицы стилей, ключевых слов и типов. Разбор текста и применение к нему стилей.

Рубрика Программирование, компьютеры и кибернетика
Вид курсовая работа
Язык русский
Дата добавления 30.05.2015
Размер файла 122,3 K

Отправить свою хорошую работу в базу знаний просто. Используйте форму, расположенную ниже

Студенты, аспиранты, молодые ученые, использующие базу знаний в своей учебе и работе, будут вам очень благодарны.

Размещено на http://www.allbest.ru/

Аннотация

В данной пояснительной записке содержится описание курсового проекта по дисциплине «Системное ПО». Цель выполнения данного курсового проекта - написание текстового редактора с подсветкой синтаксиса. Конструции языка и стили для них загружаются из XML файла. Для проверки загружаемого XML файла на корректность применяется XML Schema.

Для построения графического интерфейса пользователя используется библиотека FLTK 1.3, для работы с XML - библиотека LibXML2.

В приложении 1 приведён текст XML файла config.xml, использующегося для хранения данных о подсветке синтаксиса, в приложении 2 приведён текст XML Schema файла schema.xml, приложение 3 содержит исходный код разработанной программы.

Содержание

Аннотация

Введение

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

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

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

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

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

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

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

Заключение

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

Приложение 1

Приложение 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()

{

xmlDocPtr doc1;

const char * filename = "config.xml";

doc1 = xmlReadFile(filename, NULL, XML_PARSE_NONET);

if(is_valid(doc1, "schema.xsd") == 1)

{

int i = 0;

xmlDocPtr xmldoc = NULL;

xmlChar *uri;

if((xmldoc = xmlReadFile(filename, NULL, 0)) == NULL) return;

xmlNodePtr cur = xmlDocGetRootElement(xmldoc);

parseXMLDoc(xmldoc, "style", "entry");

parseXMLDoc(xmldoc, "keywords", "keyword");

parseXMLDoc(xmldoc, "types", "type");

xmlFree(uri);

xmlFree(color);

xmlFree(font);

}else

{

//Ошибка в XML

xmlErrorPtr XMLError;

XMLError = xmlGetLastError();

fl_alert(XMLError->message);

}

}

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

xmlDocPtr schema_doc = xmlReadFile(schema_filename, NULL, XML_PARSE_NONET);

if (schema_doc == NULL) {

fl_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) {

fl_alert("Unable to create a parser context for the schema", "Ok");

xmlFreeDoc(schema_doc);

return -2;

}

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

xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);

if (schema == NULL) {

fl_alert("the schema itself is not valid", "Ok");

xmlSchemaFreeParserCtxt(parser_ctxt);

xmlFreeDoc(schema_doc);

return -3;

}

После этого создаётся контекст проверки:

xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);

if (valid_ctxt == NULL) {

fl_alert("unable to create a validation context for the schema", "Ok");

xmlSchemaFree(schema);

xmlSchemaFreeParserCtxt(parser_ctxt);

xmlFreeDoc(schema_doc);

return -4;

}

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

int is_valid = (xmlSchemaValidateDoc(valid_ctxt, doc) == 0);

xmlSchemaFreeValidCtxt(valid_ctxt);

xmlSchemaFree(schema);

xmlSchemaFreeParserCtxt(parser_ctxt);

xmlFreeDoc(schema_doc);

return is_valid ? 1 : 0;

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

xmlErrorPtr XMLError;

XMLError = xmlGetLastError();

fl_alert(XMLError->message);

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

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

xmlDocPtr xmldoc = NULL;

if((xmldoc = xmlReadFile(filename, NULL, 0)) == NULL) return;

xmlNodePtr cur = xmlDocGetRootElement(xmldoc);

parseXMLDoc(xmldoc, "style", "entry");

parseXMLDoc(xmldoc, "keywords", "keyword");

parseXMLDoc(xmldoc, "types", "type");

xmlFree(uri);

xmlFree(color);

xmlFree(font);

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

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

{

xmlNodePtr cur;

cur = xmlDocGetRootElement(doc);

cur = cur->xmlChildrenNode;

while (cur != NULL)

{

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

{

parseNodes(doc, cur, curNode);

}

cur = cur->next;

}

}

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

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

{

xmlChar *key;

int exit(0);

cur = cur->xmlChildrenNode;

while(cur != NULL)

{

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

{

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

{

parseStyles(doc, cur, "Plain");

parseStyles(doc, cur, "Line Comments");

parseStyles(doc, cur, "Block Comments");

parseStyles(doc, cur, "Strings");

parseStyles(doc, cur, "Directives");

parseStyles(doc, cur, "Types");

parseStyles(doc, cur, "Keywords");

return;

}else

{

key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);

if(strcmp(curNode, "type") == 0)

{

code_types.push_back((const char *) key);

}else

{

code_keywords.push_back((const char *) key);

}

xmlFree(key);

}

}

cur = cur->next;

}

return;

}

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

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[0] = stylebuftemp;

}

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

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

{

return FL_BLACK;

}

или

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

{

return 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:

struct Style_Table_Entry

{

Fl_Colorcolor;

Fl_Fontfont;

intsize;

unsignedattr;

}

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

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

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

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

Fl_Text_Buffer * stylebuf;

w->editor->highlight_data(stylebuf, styletable,

sizeof(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. Герберт Шилдт «Полный справочник по XML», 2011. - 752 с.

2. К. Нейгел, Б. Ивьен, Д. Глинн, М. Скиннер, К. Уотсон Построение графического интерфейса.

3. Эндрю Троелсен библиотека FLTK 1.3, 2010. - 752 с.

4. В.В. Лабор библиотека LibXML2. Создание приложений 2013.

файл подсветка синтаксис стиль

Приложение 1

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

<language name="C++" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="schema.xsd">

<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="http://www.w3.org/2001/XMLSchema">

<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>

using namespace std;

int changed = 0;

char filename[FL_PATH_MAX] = "";

char title[FL_PATH_MAX];

Fl_Text_Buffer *textbuf = 0;

// Syntax highlighting stuff...

#define TS 14 // default editor textsize

Fl_Text_Buffer *stylebuf = 0;

Fl_Text_Display::Style_Table_Entry styletable[7];// Style table

std::vector <std::string> code_keywords;

std::vector <std::string> code_types;

std::vector <std::string>::iterator it;

std::vector <std::string>::iterator it1;

xmlChar *uri;

xmlChar *color;

xmlChar *font;

int i(0);

Fl_Text_Display::Style_Table_Entry stylebuftemp;

int is_valid(const xmlDocPtr doc, const char *schema_filename)

{

xmlDocPtr schema_doc = xmlReadFile(schema_filename, NULL, XML_PARSE_NONET);

if (schema_doc == NULL) {

fl_alert("The schema cannot be loaded or is not well-formed");

return -1;

}

xmlSchemaParserCtxtPtr parser_ctxt = xmlSchemaNewDocParserCtxt(schema_doc);

if (parser_ctxt == NULL) {

fl_alert("Unable to create a parser context for the schema", "Ok");

xmlFreeDoc(schema_doc);

return -2;

}

xmlSchemaPtr schema = xmlSchemaParse(parser_ctxt);

if (schema == NULL) {

fl_alert("the schema itself is not valid", "Ok");

xmlSchemaFreeParserCtxt(parser_ctxt);

xmlFreeDoc(schema_doc);

return -3;

}

xmlSchemaValidCtxtPtr valid_ctxt = xmlSchemaNewValidCtxt(schema);

if (valid_ctxt == NULL) {

fl_alert("unable to create a validation context for the schema", "Ok");

xmlSchemaFree(schema);

xmlSchemaFreeParserCtxt(parser_ctxt);

xmlFreeDoc(schema_doc);

return -4;

}

int is_valid = (xmlSchemaValidateDoc(valid_ctxt, doc) == 0);

xmlSchemaFreeValidCtxt(valid_ctxt);

xmlSchemaFree(schema);

xmlSchemaFreeParserCtxt(parser_ctxt);

xmlFreeDoc(schema_doc);

return is_valid ? 1 : 0;

}

unsigned int XMLValue2FLColor(const xmlChar* XMLvalue)

{

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

{

return FL_BLACK;

}

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

{

return FL_GREEN;

}

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

{

return FL_DARK_GREEN;

}

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

{

return FL_BLUE;

}

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

{

return FL_DARK_BLUE;

}

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

{

return FL_RED;

}

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

{

return FL_DARK_RED;

}

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

{

return FL_MAGENTA;

}

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

{

return FL_DARK_MAGENTA;

}

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

{

return FL_CYAN;

}

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

{

return FL_DARK_CYAN;

}

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

{

return FL_YELLOW;

}

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

{

return FL_DARK_YELLOW;

}

}

int XMLValue2FLfont(const xmlChar* XMLvalue)

{

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

{

return FL_COURIER;

}

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

{

return FL_COURIER_BOLD;

}

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

{

return FL_COURIER_ITALIC;

}

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

{

return FL_COURIER_BOLD_ITALIC;

}

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

{

return FL_HELVETICA;

}

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

{

return FL_HELVETICA_BOLD;

}

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

{

return FL_HELVETICA_ITALIC;

}

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

{

return FL_HELVETICA_BOLD_ITALIC;

}

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

{

return FL_TIMES;

}

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

{

return FL_TIMES_BOLD;

}

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

{

return FL_TIMES_ITALIC;

}

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

{

return FL_TIMES_BOLD_ITALIC;

}

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

{

return FL_SCREEN;

}

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

{

return FL_SCREEN_BOLD;

}

}

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

{

while(cur != NULL)

{

uri = xmlGetProp(cur, (const xmlChar *)"name");

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[0] = stylebuftemp;

}

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[1] = stylebuftemp;

}

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[2] = stylebuftemp;

}

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[3] = stylebuftemp;

}

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[4] = stylebuftemp;

}

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[5] = stylebuftemp;

}

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

{

color = xmlGetProp(cur, (const xmlChar *)"color");

font = xmlGetProp(cur, (const xmlChar *)"font");

stylebuftemp.color = XMLValue2FLColor(color);

stylebuftemp.font = XMLValue2FLfont(font);

stylebuftemp.size = TS;

styletable[6] = stylebuftemp;

}

cur = cur->next;

}

}

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

{

xmlChar *key;

int exit(0);

cur = cur->xmlChildrenNode;

while(cur != NULL)

{

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

{

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

{

parseStyles(doc, cur, "Plain");

parseStyles(doc, cur, "Line Comments");

parseStyles(doc, cur, "Block Comments");

parseStyles(doc, cur, "Strings");

parseStyles(doc, cur, "Directives");

parseStyles(doc, cur, "Types");

parseStyles(doc, cur, "Keywords");

return;

}else

{

key = xmlNodeListGetString(doc, cur->xmlChildrenNode, 1);

if(strcmp(curNode, "type") == 0)

{

code_types.push_back((const char *) key);

}else

{

code_keywords.push_back((const char *) key);

}

xmlFree(key);

}

}

cur = cur->next;

}

return;

}

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

{

xmlNodePtr cur;

cur = xmlDocGetRootElement(doc);

cur = cur->xmlChildrenNode;

while (cur != NULL)

{

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

{

parseNodes(doc, cur, curNode);

}

cur = cur->next;

}

}

void loadHighlightingData()

{

xmlDocPtr doc1;

const char * filename = "config.xml";

doc1 = xmlReadFile(filename, NULL, XML_PARSE_NONET);

if(is_valid(doc1, "schema.xsd") == 1)

{

int i = 0;

xmlDocPtr xmldoc = NULL;

xmlChar *uri;

if((xmldoc = xmlReadFile(filename, NULL, 0)) == NULL) return;

xmlNodePtr cur = xmlDocGetRootElement(xmldoc);

parseXMLDoc(xmldoc, "style", "entry");

parseXMLDoc(xmldoc, "keywords", "keyword");

parseXMLDoc(xmldoc, "types", "type");

xmlFree(uri);

xmlFree(color);

xmlFree(font);

}else

{

//error in XML

xmlErrorPtr XMLError;

XMLError = xmlGetLastError();

fl_alert(XMLError->message);

}

}

//

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

//

void

style_parse(const char *text,

char *style,

int length) {

char current;

int col;

int last;

char buf[255],

*bufptr;

const char *temp;

// Style letters:

//

// A - Plain

// B - Line comments

// C - Block comments

// D - Strings

// E - Directives

// F - Types

// G - Keywords

for (current = *style, col = 0, last = 0; length > 0; length --, text ++) {

if (current == 'B' || current == 'F' || current == 'G') current = 'A';

if (current == 'A') {

// Check for directives, comments, strings, and keywords...

if (col == 0 && *text == '#') {

// Set style to directive

current = 'E';

} else if (strncmp(text, "//", 2) == 0) {

current = 'B';

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

if (length == 0) break;

} else if (strncmp(text, "/*", 2) == 0) {

current = 'C';

} else if (strncmp(text, "\\\"", 2) == 0) {

// Quoted quote...

*style++ = current;

*style++ = current;

text ++;

length --;

col += 2;

continue;

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

current = 'D';

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

// Might be a keyword...

for (temp = text, bufptr = buf;

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

*bufptr++ = *temp++);

if (!islower((*temp)&255) && *temp != '_') {

*bufptr = '\0';

bufptr = buf;

it = find(code_types.begin(), code_types.end(), bufptr);

it1 = find(code_keywords.begin(), code_keywords.end(), bufptr);

if(it != code_types.end())

{

while (text < temp) {

*style++ = 'F';

text ++;

length --;

col ++;

}

text --;

length ++;

last = 1;

continue;

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

{

while (text < temp) {

*style++ = 'G';

text ++;

length --;

col ++;

}

text --;

length ++;

last = 1;

continue;

}

}

}

} else if (current == 'C' && strncmp(text, "*/", 2) == 0) {

// Close a C comment...

*style++ = current;

*style++ = current;

text ++;

length --;

current = 'A';

col += 2;

continue;

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

// Continuing in string...

if (strncmp(text, "\\\"", 2) == 0) {

// Quoted end quote...

*style++ = current;

*style++ = current;

text ++;

length --;

col += 2;

continue;

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

// End quote...

*style++ = current;

col ++;

current = 'A';

continue;

}

}

// Copy style info...

if (current == 'A' && (*text == '{' || *text == '}')) *style++ = 'G';

else *style++ = current;

col ++;

last = isalnum((*text)&255) || *text == '_' || *text == '.';

if (*text == '\n') {

// Reset column and possibly reset the style

col = 0;

if (current == 'B' || current == 'E') current = 'A';

}

}

}

//

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

//

void

style_init(void) {

char *style = new char[textbuf->length() + 1];

char *text = textbuf->text();

memset(style, 'A', textbuf->length());

style[textbuf->length()] = '\0';

if (!stylebuf) stylebuf = new Fl_Text_Buffer(textbuf->length());

style_parse(text, style, textbuf->length());

stylebuf->text(style);

delete[] style;

free(text);

}

//

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

//

void

style_unfinished_cb(int, void*) {

}

//

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

//

void

style_update(int pos,// I - Position of update

int nInserted,// I - Number of inserted chars

int nDeleted,// I - Number of deleted chars

int /*nRestyled*/,// I - Number of restyled chars

const char * /*deletedText*/,// I - Text that was deleted

void *cbArg) {// I - Callback data

intstart,// Start of text

end;// End of text

charlast,// Last style on line

*style,// Style data

*text;// Text data

// If this is just a selection change, just unselect the style buffer...

if (nInserted == 0 && nDeleted == 0) {

stylebuf->unselect();

return;

}

// Track changes in the text buffer...

if (nInserted > 0) {

// Insert characters into the style buffer...

style = new char[nInserted + 1];

memset(style, 'A', nInserted);

style[nInserted] = '\0';

stylebuf->replace(pos, pos + nDeleted, style);

delete[] style;

} else {

// Just delete characters in the style buffer...

stylebuf->remove(pos, pos + nDeleted);

}

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

// callbacks...

stylebuf->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...

start = textbuf->line_start(pos);

// if (start > 0) start = textbuf->line_start(start - 1);

end = textbuf->line_end(pos + nInserted);

text = textbuf->text_range(start, end);

style = stylebuf->text_range(start, end);

if (start==end)

last = 0;

else

last = style[end - start - 1];

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

// start, end, text, style, last);

style_parse(text, style, end - start);

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

// style, style[end - start - 1]);

stylebuf->replace(start, end, style);

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

if (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...

free(text);

free(style);

end = textbuf->length();

text = textbuf->text_range(start, end);

style = stylebuf->text_range(start, end);

style_parse(text, style, end - start);

stylebuf->replace(start, end, style);

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

}

free(text);

free(style);

}

// Editor window functions and class...

void save_cb();

void saveas_cb();

void find2_cb(Fl_Widget*, void*);

void replall_cb(Fl_Widget*, void*);

void replace2_cb(Fl_Widget*, void*);

void replcan_cb(Fl_Widget*, void*);

class EditorWindow : public Fl_Double_Window {

public:

EditorWindow(int w, int h, const char* t);

~EditorWindow();

Fl_Window *replace_dlg;

Fl_Input *replace_find;

Fl_Input *replace_with;

Fl_Button *replace_all;

Fl_Return_Button *replace_next;

Fl_Button *replace_cancel;

Fl_Text_Editor *editor;

char search[256];

};

EditorWindow::EditorWindow(int w, int h, const char* t) : Fl_Double_Window(w, h, t) {

replace_dlg = new Fl_Window(300, 105, "Replace");

replace_find = new Fl_Input(80, 10, 210, 25, "Find:");

replace_find->align(FL_ALIGN_LEFT);

replace_with = new Fl_Input(80, 40, 210, 25, "Replace:");

replace_with->align(FL_ALIGN_LEFT);

replace_all = new Fl_Button(10, 70, 90, 25, "Replace All");

replace_all->callback((Fl_Callback *)replall_cb, this);

replace_next = new Fl_Return_Button(105, 70, 120, 25, "Replace Next");

replace_next->callback((Fl_Callback *)replace2_cb, this);

replace_cancel = new Fl_Button(230, 70, 60, 25, "Cancel");

replace_cancel->callback((Fl_Callback *)replcan_cb, this);

replace_dlg->end();

replace_dlg->set_non_modal();

editor = 0;

*search = (char)0;

loadHighlightingData();

}

EditorWindow::~EditorWindow() {

delete replace_dlg;

}

int check_save(void) {

if (!changed) return 1;

int r = fl_choice("The current file has not been saved.\n"

"Would you like to save it now?",

"Cancel", "Save", "Don't Save");

if (r == 1) {

save_cb(); // Save the file...

return !changed;

}

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

}

int loading = 0;

void load_file(const char *newfile, int ipos) {

loading = 1;

int insert = (ipos != -1);

changed = insert;

if (!insert) strcpy(filename, "");

int r;

if (!insert) r = textbuf->loadfile(newfile);

else r = textbuf->insertfile(newfile, ipos);

//changed = changed || textbuf->input_file_was_transcoded;

if (r)

fl_alert("Error reading from file \'%s\':\n%s.", newfile, strerror(errno));

else

if (!insert) strcpy(filename, newfile);

loading = 0;

textbuf->call_modify_callbacks();

}

void save_file(const char *newfile) {

if (textbuf->savefile(newfile))

fl_alert("Error writing to file \'%s\':\n%s.", newfile, strerror(errno));

else

strcpy(filename, newfile);

changed = 0;

textbuf->call_modify_callbacks();

}

void copy_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

Fl_Text_Editor::kf_copy(0, e->editor);

}

void cut_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

Fl_Text_Editor::kf_cut(0, e->editor);

}

void delete_cb(Fl_Widget*, void*) {

textbuf->remove_selection();

}

void find_cb(Fl_Widget* w, void* v) {

EditorWindow* e = (EditorWindow*)v;

const char *val;

val = fl_input("Search String:", e->search);

if (val != NULL) {

// User entered a string - go find it!

strcpy(e->search, val);

find2_cb(w, v);

}

}

void find2_cb(Fl_Widget* w, void* v) {

EditorWindow* e = (EditorWindow*)v;

if (e->search[0] == '\0') {

// Search string is blank; get a new one...

find_cb(w, v);

return;

}

int pos = e->editor->insert_position();

int found = textbuf->search_forward(pos, e->search, &pos);

if (found) {

// Found a match; select and update the position...

textbuf->select(pos, pos+strlen(e->search));

e->editor->insert_position(pos+strlen(e->search));

e->editor->show_insert_position();

}

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

}

void set_title(Fl_Window* w) {

if (filename[0] == '\0') strcpy(title, "Untitled");

else {

char *slash;

slash = strrchr(filename, '/');

#ifdef WIN32

if (slash == NULL) slash = strrchr(filename, '\\');

#endif

if (slash != NULL) strcpy(title, slash + 1);

else strcpy(title, filename);

}

if (changed) strcat(title, " (modified)");

w->label(title);

}

void changed_cb(int, int nInserted, int nDeleted,int, const char*, void* v) {

if ((nInserted || nDeleted) && !loading) changed = 1;

EditorWindow *w = (EditorWindow *)v;

set_title(w);

if (loading) w->editor->show_insert_position();

}

void new_cb(Fl_Widget*, void*) {

if (!check_save()) return;

filename[0] = '\0';

textbuf->select(0, textbuf->length());

textbuf->remove_selection();

changed = 0;

textbuf->call_modify_callbacks();

}

void open_cb(Fl_Widget*, void*) {

if (!check_save()) return;

Fl_Native_File_Chooser fnfc;

fnfc.title("Open file");

fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);

if ( fnfc.show() ) return;

load_file(fnfc.filename(), -1);

}

void insert_cb(Fl_Widget*, void *v) {

Fl_Native_File_Chooser fnfc;

fnfc.title("Insert file");

fnfc.type(Fl_Native_File_Chooser::BROWSE_FILE);

if ( fnfc.show() ) return;

EditorWindow *w = (EditorWindow *)v;

load_file(fnfc.filename(), w->editor->insert_position());

}

void paste_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

Fl_Text_Editor::kf_paste(0, e->editor);

}

int num_windows = 0;

void close_cb(Fl_Widget*, void* v) {

EditorWindow* w = (EditorWindow*)v;

if (num_windows == 1) {

if (!check_save())

return;

}

w->hide();

w->editor->buffer(0);

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

textbuf->remove_modify_callback(changed_cb, w);

Fl::delete_widget(w);

num_windows--;

if (!num_windows) exit(0);

}

void quit_cb(Fl_Widget*, void*) {

if (changed && !check_save())

return;

exit(0);

}

void replace_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

e->replace_dlg->show();

}

void replace2_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

const char *find = e->replace_find->value();

const char *replace = e->replace_with->value();

if (find[0] == '\0') {

// Search string is blank; get a new one...

e->replace_dlg->show();

return;

}

e->replace_dlg->hide();

int pos = e->editor->insert_position();

int found = textbuf->search_forward(pos, find, &pos);

if (found) {

// Found a match; update the position and replace text...

textbuf->select(pos, pos+strlen(find));

textbuf->remove_selection();

textbuf->insert(pos, replace);

textbuf->select(pos, pos+strlen(replace));

e->editor->insert_position(pos+strlen(replace));

e->editor->show_insert_position();

}

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

}

void replall_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

const char *find = e->replace_find->value();

const char *replace = e->replace_with->value();

find = e->replace_find->value();

if (find[0] == '\0') {

// Search string is blank; get a new one...

e->replace_dlg->show();

return;

}

e->replace_dlg->hide();

e->editor->insert_position(0);

int times = 0;

// Loop through the whole string

for (int found = 1; found;) {

int pos = e->editor->insert_position();

found = textbuf->search_forward(pos, find, &pos);

if (found) {

// Found a match; update the position and replace text...

textbuf->select(pos, pos+strlen(find));

textbuf->remove_selection();

textbuf->insert(pos, replace);

e->editor->insert_position(pos+strlen(replace));

e->editor->show_insert_position();

times++;

}

}

if (times) fl_message("Replaced %d occurrences.", times);

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

}

void replcan_cb(Fl_Widget*, void* v) {

EditorWindow* e = (EditorWindow*)v;

e->replace_dlg->hide();

}

void save_cb() {

if (filename[0] == '\0') {

// No filename - get one!

saveas_cb();

return;

}

else save_file(filename);

}

void saveas_cb() {

Fl_Native_File_Chooser fnfc;

fnfc.title("Save File As?");

fnfc.type(Fl_Native_File_Chooser::BROWSE_SAVE_FILE);

if ( fnfc.show() ) return;

save_file(fnfc.filename());

}

Fl_Window* new_view();

void view_cb(Fl_Widget*, void*) {

Fl_Window* w = new_view();

w->show();

}

Fl_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 }

};

Fl_Window* new_view() {

EditorWindow* w = new EditorWindow(660, 400, title);

w->begin();

Fl_Menu_Bar* m = new Fl_Menu_Bar(0, 0, 660, 30);

m->copy(menuitems, w);

w->editor = new Fl_Text_Editor(0, 30, 660, 370);

w->editor->textfont(FL_COURIER);

w->editor->textsize(TS);

w->editor->buffer(textbuf);

w->editor->highlight_data(stylebuf, styletable,

sizeof(styletable) / sizeof(styletable[0]),

'A', style_unfinished_cb, 0);

textbuf->text();

style_init();

w->end();

w->resizable(w->editor);

w->callback((Fl_Callback *)close_cb, w);

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

textbuf->add_modify_callback(changed_cb, w);

textbuf->call_modify_callbacks();

num_windows++;

return w;

}

int main(int argc, char **argv) {

LIBXML_TEST_VERSION;

textbuf = new Fl_Text_Buffer;

style_init();

Fl_Window* window = new_view();

window->show(1, argv);

if (argc > 1) load_file(argv[1], -1);

return Fl::run();

}

Размещено на Allbest.ru


Подобные документы

  • Разработка текстового редактора с подсветкой синтаксиса языков программирования. Загрузка из XML-файла настроек для подсветки синтаксиса и конструкций языка. Формат файлов конфигурации и проверки. Разбор текста и применение к нему стилей, тестовый пример.

    курсовая работа [141,6 K], добавлен 13.03.2013

  • Классификация текстовых редакторов и процессоров. Способы хранения текста в файле. Форматирование документа и его редактирование. Среда текстового редактора. Автоматическая проверка орфографии и синтаксиса текста, автотекст, автозамена, гипертекст.

    курсовая работа [35,0 K], добавлен 25.04.2013

  • Классификация и возможности текстовых редакторов. Среда текстового редактора Microsoft Word 2003. Процесс редактирования текста, его копирование и перемещение. Проверка орфографии и синтаксиса, автотекст и автозамена. Пример гипертекстового документа.

    курсовая работа [2,4 M], добавлен 25.04.2013

  • Создание сайта при помощи HTML и CSS. Язык гипертекстовой разметки HTML и таблица стилей CSS. Основные понятия об этих языках, этапы и алгоритмы программного обеспечения. Добавление стилей в документ. Свойства элементов, принцип построения Web-страницы.

    курсовая работа [2,9 M], добавлен 12.01.2016

  • Применение правил грамматики. Синтаксический анализатор, нис- и восходящий разбор, полный перебор правил подстановки. Классификация грамматик по Хомскому. Определение языков с помощью автоматов. Форма Бекуса-Наура описания синтаксиса формальных языков.

    лекция [270,1 K], добавлен 19.10.2014

  • Главная идея LaTeX, возможности системы. Структура документа - текстового файла, содержащего специальные команды языка разметки. Формат текста и вспомогательные программы. Отображение математических и других формул, символы функций и исходные команды.

    курсовая работа [704,6 K], добавлен 21.02.2015

  • Разработка исходного XML-документа, который будет содержать данные варианта. Разработка таблицы стилей XSLT для преобразования исходного XML-документа исходного XML-документ с заданной структурой. Анализ базового класса, содержащего виртуальные методы.

    курсовая работа [1,3 M], добавлен 01.05.2019

  • Каскадные Таблицы Стилей (CSS). Возможности для работы со шрифтами. Расширение свойств тегов. Способы определения стилей форматирования. Классы и идентификаторы. Работа со шрифтами. Свободное позиционирование элементов. Свойства блоков текста.

    реферат [129,5 K], добавлен 17.11.2008

  • Описание синтаксиса и семантики входного языка. Описание типов лексем, определение их синтаксиса. Построение диаграммы лексического анализатора, а также его таблицы, тестирование. Построение КС-грамматики входного языка. Описание промежуточного языка.

    курсовая работа [83,0 K], добавлен 23.01.2014

  • Составление Win32 App проекта - простейшего текстового редактора, который позволяет выполнять такие операции: редактирование текста, копирование и вставку из одного окна проекта в другое окно проекта. Методы вызова диалогов сохранения и открытия файла.

    курсовая работа [716,3 K], добавлен 09.11.2010

Работы в архивах красиво оформлены согласно требованиям ВУЗов и содержат рисунки, диаграммы, формулы и т.д.
PPT, PPTX и PDF-файлы представлены только в архивах.
Рекомендуем скачать работу.