Очередная терминалка

Когда я читал ветку, мне захотелось написать аналогичный терминал. Just for lulz. Пару дней это таки заняло, но в результате получилось нечто такое:

Из плюсов по сравнению с прообразом — чуть большая функциональность и возможность распахнуть окошко.
Установки не требует. Описания тоже. Чтобы сохраняло настройки — нужно в меню Store settings выбрать, куда их сохранять. Чтобы удалить сохраненные настройки (деинсталляция, ага) нужно выбрать Store settings -> Nowhere.
Сам терминал (версия 1.1.0.22). Зеркало.
Исходники. Delphi 7, стандартные компоненты.
Терминал 2.0 alpha. Библиотеки для сборки из сырков.
  • +5
  • 07 февраля 2013, 08:59
  • Vga

Комментарии (135)

RSS свернуть / развернуть
Вывод в RichEdit — ужасная тормозуха:)
0
Это еще мягко сказано. Причем я даже хз, RichEdit это так тормозит или его VCL-обертка.
А какие ему есть альтернативы, кроме самописного контрола?
0
Одно слово — Canvas.
0
Одно слово — Canvas.
Canvas как альтернатива или Canvas как причина тормозов?
0
Memo и RichEdit тормозят из-за своей громоздкости. Если хочется организовать вывод быстрее, надо использовать голый Canvas.
0
Это слишком капитально. Мне совершенно не хочется нырять в отрисовку текста со всеми ее заморочками и особенно выделением. Да и это потребует больше кода, чем вся прога сейчас.
А из альтернатив, где все уже готово с полпинка вспоминается только SynEdit. Хотя… Возможно еще TWebBrowser прокатит.
0
Возможно еще TWebBrowser прокатит.
Он реально будет быстрее.
0
у мемо я почему то тормозов не помню.
0
Возможно туп и глуп но:
обратил внимание если в компонент Memo в Builder добавлять много текста через Memo1->Text=Memo1->Text+… то тормоза аццкие даже если выключать на время заполнения Memo, если же Memo1->Lines->Add() то все более пристойно
0
У меня как раз второй вариант. Не помогает.
0
Потому, что Memo наследник TStringList, тот в свою очередь от TList. И метод add() родной для них. А обращение к свойству Text вызывает кучу методов, чтобы склеить все элементы списка в одну кашу, и не удивлюсь, что даже в цикле (забыл уже реализацию в VCL за давностью лет)
0
Это не совсем так. Во первых, TMemo — наследник TWinControl, ЕМНИП (возможно не прямой). Во вторых, наследник TStrings — его свойство Lines, и TStrings — совсем не то же, что TStringList или, тем более, TList, это всего лишь общий интерфейс для всего, к чему применим интерфейс списка строк. Скорее всего Memo.Lines имеет весьма мало отношения к TStringList и работает с Memo.Text. Впрочем, что и через что у Memo и RichEdit работает я не изучал. Хотя стоило бы.
Работа с Lines может быть быстрее, если использовать методы BeginUpdate/EndUpdate — в этом случае реальное обновление содержимого TMemo/TRichEdit произойдет только после вызова EndUpdate, сократив количество накладных операций. К сожалению, мне это не подходит, т.к. раскрашивать вывод в TRichEdit приходится черезжопно и с блокировкой на время обновления это не особо совместимо.
0
Да, скорее так, говорю же — забыл полную иерархию. Но TList там всё-таки был, посмотрите реализацию TStrings, скорее всего от него унаследован (вроде там был список указателей на строки, и к ним привязка, за счёт этого достигалась хорошая скорость работы всех производных list'ов).
0
Нет, последовательность наследования там примерно такая:
TObject <- TPersistent <- TStrings <- TStringList
                                   <- TMemo.Lines

TStrings не содержит вообще никаких средств хранения самих строк. Они есть в TStringList, как раз на основе TList ЕМНИП. А вот у TMemo и TRichEdit это не более чем интерфейс к внутреннему представлению текста.
0
А, вон как.
0
Они есть в TStringList, как раз на основе TList ЕМНИП.
Кстати, нифига подобного. TStringList ведет внутри себя собственный массив структурок вида record S: string; O: TObject; end; Видимо, переупорядочивание и прочее выполняются как операции над этим массивом, благо гонять туда-сюда 8-байтные структурки не так уж накладно (сами строки всегда выделяются в куче). А перевыделения самого массива оптимизированы.
0
нене, это специальный документированный функционал TStringList, т.е. доп. поле для пользователя. К строке можно прицепить указатель на любой объект, я этим часто пользовался.
0
Если бы ты удосужился заглянуть в код, то увидел бы что там на этой фиче пол-интерфейса построено)
И я знаю, зачем там указатель на объект. Я говорю, что TStringList вообще не имеет отношения к TList — полностью независимая реализация. Данные хранятся в виде массива таких вот структур, хранящих ссылки на итем (строку и связанный объект). Впрочем, TList скорее всего устроен примерно так же, только вместо массива структурок хранит массив указателей.
0
Загляну обязательно, сейчас не на чем :)
0
В смсле, TStringList может тупо заменить собой TList, + строковый функционал.
0
TList для списка указателей таки эффективней. Ну и я в основном говорю о изначальной предпосылке:
Memo наследник TStringList, тот в свою очередь от TList
TStringList не только не наследник TList, но и вообще никакой связи с ним не имеет. Даже мое предположение:
Они есть в TStringList, как раз на основе TList ЕМНИП.
Тоже оказалось ошибочным.
0
Да понял, понял. Последний раз кодил на дельфях в 2008м (ой, уже 5 лет
пролетело)
0
А вот у TMemo и TRichEdit это не более чем интерфейс к внутреннему представлению текста.
А точнее даже к Rich Edit API. Все его функции работают через посылку сообщений редактору. Вот, например, поддержка свойств Items и Count:
function TRichEditStrings.GetCount: Integer;
begin
  Result := SendMessage(RichEdit.Handle, EM_GETLINECOUNT, 0, 0);
  if SendMessage(RichEdit.Handle, EM_LINELENGTH, SendMessage(RichEdit.Handle,
    EM_LINEINDEX, Result - 1, 0), 0) = 0 then Dec(Result);
end;

function TRichEditStrings.Get(Index: Integer): string;
var
  Text: array[0..4095] of Char;
  L: Integer;
begin
  Word((@Text)^) := SizeOf(Text);
  L := SendMessage(RichEdit.Handle, EM_GETLINE, Index, Longint(@Text));
  if (Text[L - 2] = #13) and (Text[L - 1] = #10) then Dec(L, 2);
  SetString(Result, Text, L);
end;

procedure TRichEditStrings.Put(Index: Integer; const S: string);
var
  Selection: TCharRange;
begin
  if Index >= 0 then
  begin
    Selection.cpMin := SendMessage(RichEdit.Handle, EM_LINEINDEX, Index, 0);
    if Selection.cpMin <> -1 then
    begin
      Selection.cpMax := Selection.cpMin +
        SendMessage(RichEdit.Handle, EM_LINELENGTH, Selection.cpMin, 0);
      SendMessage(RichEdit.Handle, EM_EXSETSEL, 0, Longint(@Selection));
      SendMessage(RichEdit.Handle, EM_REPLACESEL, 0, Longint(PChar(S)));
    end;
  end;
end;

Короче, все тормоза растут из самого RichEdit.
0
Во как завернули!
Кстати, я использовал какой-то сторонний компонент, когда искал редактор, который не тормозит на большом количестве строк. И таки нашел! Но вот название забыл, хоть убей…
0
Там ещё много промежуточных TCustomЛяляля может быть, в VCL любили их подкладывать.
0
И неспроста, это общие интерфейсы для различных вариантов реализации (скажем, TCustomMemoryStream — общая база для TMemoryStream, TResourceStream, еще каких-то). Для разновидностей списков строк TStrings как раз таким TCustomLalala и является.
0
А что если запретить перерисовку ему на время ввода больших объемов текста, а потом перерисовать разом?
RichEdit1.Perform(WM_SETREDRAW,0,0); // Запрещаем перерисовку
// ...
RichEdit1.Perform(WM_SETREDRAW,1,0); // Разрешаем перерисовку
RichEdit1.Repaint; // и сразу перерисовываем
Во время приема данных можно запретить перерисовку и раз в 500 (250/100) ms перерисовывать, хоть по таймеру.
0
это обязателно надо делать
0
А вот это попробую. Как, впрочем, и Begin/EndUpdate. Может и не сломается.
0
Поковырял сорцы RichEdit'а. Как раз эту операцию TRichEdit.Lines.BeginUpdate/EndUpdate и делает. Так что вместо отправки сообщений лучше вызывать эти две функции.
0
а седьмые дельфи работают даже в семерке? удивлен.
0
Delphi — не знаю, а вот собранные ей проги — вполне. В семерке я только скрин снимал, по техническим причинам. И тот закосячил))
0
дорисуйте карандашом =)
0
Карандашом я только чертить умею, увы)
0
Работают. Хотя часть функций и глючит, в основ касающиеся распределения памяти.
0
В самой Delphi или в RTL?
0
Есть же putty.
0
  • avatar
  • m0xf
  • 07 февраля 2013, 09:51
А еще HyperTerminal, Bray Terminal и wTerm — только из того, что у меня имеется, не считая встроенного в разные ардуины и микропаскали. Но когда это кому-то мешало написать еще один велосипед?
0
написать свой велосипед это даже полезно, с точки зрения практики и опыта
0
Тоже буквально на днях писал свой велосипед, но только с небольшим дополнением для удобного управления мкашкой его отладкой.
0
1. Уберите настройки с основного окна — сделайте отдельный диалог.
2. Я пользуюсь только Tera Term — всем устраивает, нафиг что-то другое?
0
1. Так задумано. Это фича.
2. Уже спрашивали.
0
Ужасная фича
0
Не нравится — не используй. Терминалов — как собак нерезаных, и даже больше, на любой вкус. Мне для определенных задач нравится именно такой, с настройками в кликовой доступности. Правда, использую я обычно Bray, он как раз такой интерфейс имеет, только понавороченней.
0
cutecom часто использую. Настройки тоже в главном окне.
0
Ты ссылку забыл)
0
0
Ой, оно на кьюте и не собранное) Да и как-то не сильно впечатляет после Bray'я. Он страшный, но пофункциональней)
0
Там скриншот страшный, так он вполне ничего. Домой доберусь — покажу.
Зато исходники есть :)
Хотя, на Qt такое пишется за час…
0
Не, брей страшный.
0
Нифига не соглашусь. Тут они как раз перед глазами. Мы же не со стандартным модемом связываемся, а работаем с железками, с которыми приходится мудохаться, соображая, то ли сопли виноваты в отсутствии связи, то ли неправильно порт сконфигурирован, то ли терминал…
+1
Молчу-молчу :) На вкус и цвет — все фломастеры разные.
0
Примного благодарствую, просто, удобно. Только расставаться не захочется когда выйдет мсвиндовс28 или компы акупирует арм. Сам давно на Java программлю, кому больше нравится на .Net
0
а HEX и передачи одной строкой (как в Brays terminal) нет?
0
допишите. автор ведь сырки отдал.
0
давно написал, еще и с скриптованием (Modbus и т.д.)
0
Hex есть, два нижних комбобокса задают кодировку приема и передачи. А что за «передача одной строкой»?
0
А что за «передача одной строкой»?
протелепатирую. передача не в процессе набора, а по Enter`у.
0
точно. Без этого невозможно настроить модули HC04
0
уж лучше перключать чекбоксом. а то некоторое железо наоборот захлебывается, когда кормишь его строкой сразу.
0
*переключать
0
Оно только так и умеет. Вообще, именно на Bray Terminal оно больше всего и похоже. Только Lite version)
0
Ради прикола собрал проект в Lazarus. После маленькой правки собралось и запустилось. Размер файла получился каких то 1,5 мег. Жаль, проверить работу самого порта дома нечем.
0
  • avatar
  • aen
  • 08 февраля 2013, 00:54
Только кроссплатформенней оно от того не станет. COMPort на WinAPI написан, да и внутри ЕМНИП без него не обошлось.
0
У меня скрин снялся. Но что забавно, со второй попытки. На первой пропадала галочка Captions прям в момент нажатия Alt+PrintScreen
+1
  • avatar
  • ks_
  • 08 февраля 2013, 06:11
Похоже, оно как-то с принтскрином и связано в Win7. В XP скрин нормально снимается. Какие-то косяки с перерисовкой, в виндах по ХР включительно не замечал такого за VCL D7.
0
Обновил программу — добавил BeginUpdate/EndUpdate при добавлении текста в лог. Стало заметно быстрее.
0
  • avatar
  • Vga
  • 10 февраля 2013, 22:27
Не совсем понял из комментов: прога позволяет сохранять весь поток в виде лог-файла? Незаменимая вещь при сборе отладочной статистики…
0
Нет, лог в данном случае — окошко, куда падает история принятого/отправленного. Воооон тот TRichEdit. Добавил отключение перерисовки на время апдейта и оно стало куда быстрее. Раз так в 10 как минимум.
0
А можешь докрутить отправку прямиком в файл? А то я на дельфях лет 10 не программировал, да и все программирование у меня сводилось к паре простых окошек с кнопочками. Полезу сам — вообще все испорчу…
0
Вообще, терминалка задумывалась как предельно простая. При необходимости можно в окне лога сделать Ctrl-A Ctrl-C и сохранить в файл блокнотом.
0
это хорошо, когда объем информации небольшой. А мне нужно набрать статистику по работе устройства, когда оно в течение какого-то времени работает и проходя определенные контрольные точки спамит в порт информацию о состоянии. Я не уверен что просто накопленная информация в окне влезет (если окно со скролом) и в добавок еще не подвесит всю терминалку. (представь что прога работает часа 2 и каждую секунду к примеру кидает несколько байт в порт… и при этом сидеть и смотреть в терминал 2 часа чтобы отыскать возможный сбой занятие весьма неинтересное, лучше потом файл проанализировать)

Потому кнопка записи лога сложности не добавит, а функциональность увеличит.
0
Не, не хочу я такую функциональность добавлять. Она не соответствует моему видению проекта. В твоем случае, я думаю, можно обойтись командой COM1 > log.txt)
+1
Но если хочешь, можешь переделать. Прием в методе TFormMain.RecvTimerTimer. Выкинь все вложенные функции кроме ReadToBuffer и замени код самого метода на нечто вроде
if not Assigned(FCOMPort) or not Assigned(FOutFile) then Exit;
  ReadToBuffer;
  FOutFile.Write(FRecvBuffer[1], Length(FRecvBuffer);
  FRecvBuffer:='';

Где FOutFile — TFileStream для записи выходного файла. Его создание, уничтожение и выбор имени файла пиши сам. Если же хочешь сохранить «парсер» принятого — то есть методы SetLogUpdateState и AddToLog. Первый можно игнорировать, а во второй сыплются распарсенные строки для добавления в TRichEdit.
0
спасибо, если будет время — покопаюсь. а может в самом деле буду пользоваться COM > log.txt. Я просто все время забываю, работает ли эта строка под виндой :)
0
Гугол в помощь, мил человек. И да хранит тебя святой байт. :)
0
Работает, куда она денется. Только порт сперва нужно настроить. В диспетчере устройств, например. И вроде есть что-то консольное для настройки порта, но не помню что.
0
MODE COM?
0
и не забывай, что > перезаписывает, а >> добавляет.
0
Выловил очередную ошибку — терминал не работал с портами выше COM9 (да и не видел их). Обновил до версии 1.0.0.20.
0
  • avatar
  • Vga
  • 23 февраля 2013, 17:03
Хм, лол, еще один баг. На сей раз совсем идиотский. Теперь выбранный порт не только сохраняется в файл настроек, но и загружается оттуда) Версия 1.0.0.21.
0
А что в этом плохого? Какой порт был открыт в последний сеанс, вероятнее всего тот и будет запрошен в очередной. Добавить автоконнект и вообще прелесть будет.
0
Я же сказал, он не загружался из настроек. Т.е. при запуске всегда выбирался первый доступный порт. Причем ошибка такая прелестная… Читаем из конфига номер порта, ищем строчку с этим портом в комбобоксе и… выбираем первый элемент комбобокса)
0
Здравствуйте.
Vga, а можно добавить время приема/отправки пакета с точностью до миллисекунд?
Спасибо.
0
  • avatar
  • Denya
  • 28 февраля 2013, 18:04
Об этом я думал. Время добавить можно, но ни о каких миллисекундах под виндой (тем более с приемом по таймеру) и речи идти не может. Т.е. вывести-то их можно, но врать будет беспощадно.
0
В таком случае с точностью до секунд было бы неплохо. Иногда информация о времени приема пакета весьма существенна.
0
Сделал. Таймштампы отображаются, если поставить галочку Captions. Версия 1.1.0.22.
0
Огонь! Спасибо большое!
0
Алсо, небольшой трик. В настройках есть запись MaxHistory, по дефолту равная 10. При желании можно подправить. Скажем, 8 — чтобы в выпадающем списке не было прокрутки. Или 100 — чтобы ее хранилось побольше, побольше. Настройки лежат в VSTerm.ini или в HKEY_CURRENT_USER\Software\VSTerm.
0
  • avatar
  • Vga
  • 01 марта 2013, 09:23
Хорошая программа. Спасибо большое!
0
Программка убилась антивирусом. Вот печаль. Говорит — нашла трояна-даунлоадера. И скачать снова не даёт.
0
Гы. Вероятно побочный эффект от exe-пакера. Варианты:
1) Скачать еще раз, при выключенном антивирусе. Внести в исключения. Если мой комп не заражен и если WinUPack не содержит закладок — безопасно.
2) Подождать обновления базы антивируса — может, срабатывание исключат. Маловероятно, впрочем.
3) Собрать из сорцов самому, без использования пакеров. Хотя были случаи, когда антивирус реагировал на программу вида «program Foo; begin end.», причем это был не Induc.
4) Если не нужны таймштампы — можно слить предыдущую версию. Правда, для этого нужен svn-клиент, сливать командой «svn export -r 146 vgasoft.googlecode.com/svn/Binaries/Terminal/VSTerm.exe». Не исключено, впрочем, что антивирь и на ту версию сработает.

Какой антивирус, кстати? Я всегда запрещаю антивирусу самодеятельность.
0
Тьфу, парсер нагадил. Команда:
svn export -r 146 http://vgasoft.googlecode.com/svn/Binaries/Terminal/VSTerm.exe
0
Впрочем, метод 4 не работает, VirusTotal на версию 1.0 выдает точно такие же результаты, как и на 1.1. Видимо, пакер не по вкусу.
0
Хе-хе, иллюстрация к вопросу «почему не стоит пользоваться exe-пакерами»:
До upack'а.
После upack'а.
0
О_О. Фигасе :) Антивирусник у меня Comodo, раньше не ругался а тут внезапно взял и грохнул. Видимо — наоборот, с очередным обновлением и новыми базами решил, радостный, что от трояна систему спас :)
0
с очередным обновлением и новыми базами решил, радостный, что от трояна систему спас :)
Что детект пришел с очередным обновлением — это, как раз, очевидно. Есть некоторая вероятность, что его поправят в каком-то из будущих обновлений как ложный, но это маловероятно.
0
А этот пример еще примечательнее :)
0
ОК, неупакованная версия 1.1.0.22. MD5 047859D00F364EABBA37AD9F14733488.
0
ОК, неупакованная версия 1.1.0.22. MD5 047859D00F364EABBA37AD9F14733488.
ссылка не работает.
0
Когда скачал с файлообменника то увидел такое радостное сообщение

У тебя чо там троян сидит?
0
ссылка не работает.
Разумеется не работает, это же slil.ru. Он удаляет файл через две недели.
У тебя чо там троян сидит?
У половины антивирусов аллергия на exe-пакеры. Собери чистый или добавь в исключения. Ну или поставь другой антивирус — MSE и AVG тоже бесплатные, но хотя бы на Upack не ругаются. NOD32 тоже не ругается, но платный.
0
P.S. Для скриншотов окон есть Alt+PrintScreen, фоткает только активное окно, не требуя дополнительной обрезки и вытирания лишнего.
+1
Это мне известно. А как потом вставить его в коммент?
0
Вставить в любой редактор, хоть в пайнт, и сохранить в PNG или GIF. В чем-то же ты этот скрин обрезал, да поля затирал.
+1
Не а ничего не затирал. Вставлял в прогу RUSPLAN.
0
Здравствуйте.
Уважаемый Vga, а можно как-то добавить функцию отключения приема во время передачи файлов?
Иногда передача идет по однопроводной шине и все отосланные данные забивают консоль мусором…
Спасибо.
0
Можно. Правда, версию 1.х я больше не поддерживаю, но в альфу 2.0 добавил. Пробуй (ссылку на альфу добавил в топик)
0
P.S. Отключать надо вручную, переключив режим приема на Disable перед отправкой файла.
0
А можно чтобы в автомате отключалось, а после передачи активировалось, т.к. девайс после принятия последнего байта рапартует в порт, все ли успешно принято, и сошлась ли контрольная сумма. В ручном переключении ответ девайса не словить…
Спасибо.
0
Это сложнее. Выключать без опции мне не хочется (девайс, в принципе, может рапортовать прямо во время передачи файла), лишнюю опцию притыкать тоже не хочу.
Плюс на это накладывается прием по таймеру. Полагаю, оно будет или захватывать хороший кусок мусора, или проморгает ответ.
0
А если оставить выключение в ручном режиме и добавить еще, что-то типа галки Captions (под ней)?
Я думаю можно обойтись без таймера, просто включать прием сразу после окончании передачи файла, тот размер мусора все равно не сравнится с полным объемом (при передаче файлов более 500кБ терминалка начинает подвисать, приходится в ручную очищать окно Ctrl+N)…
0
Новая версия тоже подвисает?
0
Да, новая работает намного лучше, только в момент подгрузки массива принятых данных в окно терминалки, идет короткая пауза в передаче.
И все-таки, если будет возможность добавить функцию автоматического отключения приема на время передачи файла, было бы очень круто!
Спасибо!
0
Добавил вариант режима приема «Mute file sending». Костыльновато и не слишком интуитивно — так, я даже сам не сразу понял, что он выставляет после отправки файла тот режим приема, который был сохранен в настройках программы :)
Как и следовало ожидать, хвост файла в лог таки падает. Но когда я переделаю прием с таймера на события — возможно будет иначе.
0
Хвостик совсем короткий, я думаю не существенно. Вот только установка режима Mute полностью ручная…
Было бы просто супер, если бы с передачей файла режим Receive автоматом переключался в Disable и автоматом возвращался обратно после передачи файла.
Я думаю установить эту настройку под Caption было бы удобнее всего…
Спасибо.
0
Сделал.
+1
Терминалка лучшая, спасибо большое!!!
+1
Я не знаю, связано это с терминалкой или с драйверами на CH340G, но меня очень напугало такое поведение на Win7. Я всего-лишь хотел установить кастомную скорость.
0
О, бсодик. Не, такое только из дров устроить можно, так что благодари китайцев. И не ставь нестандартные скорости на этом адаптере)
Я тестировал на FT232, оно к левым скоростям относится более благосклонно.
0
Кстати, есть такая тулза от NirSoft — BlueScreenView. В ней можно открыть дамп креша и посмотреть, в каком модуле оно упало.
+1
О, спасибо. Прога полезная. Посмотрел, реально из-за дров китайских.
0
Кстати, я этот адаптер купил, потому что срочно нужно было подключиться к uart, а у меня был только Bluetooth HC-06. Так вот этот HC-06 никак не работает на винде. Перепробовал 3 разных bluetooth адаптера. Все они подключаются к HC-06, в системе появляется виртуальный COM-порт, но при попытке его открыть все терминалки подвисают секунд на 20, а потом этот порт пропадает из системы. Проблема в HC-06 или я что-то не так делаю?
0
Ты, кстати, не нулевую скорость выставил случаем?) Судя по коду ошибки, оно упало из-за целочисленного деления на ноль в недрах драйвера.
0
Я крутил колесико мышки. Докрутил до кастомной скорости. Ничего не успел понять как оно вдруг бахнуло.
0
Странно. При выборе кастома должно вывалиться окошко для ввода скорости (по дефолту, кстати, именно ноль), а примениться только на Enter/OK.
0
Упс, а применяется-то оно незамедлительно. Так что да, дрова не оценили попытку выставить скорость в ноль)
Пофиксил.
0
Еще один момент. При переключении на программу каждый раз приходится наводить мышку на поле ввода и клацать левой кнопкой. Нельзя ли сделать так, что бы фокус сразу устанавливался в поле ввода и можно было бы сразу вводить текст?
0
Ага, есть такая проблема. Вроде пофиксил, проверяй.
0
Отлично! Теперь намного удобнее. Спасибо.
0
Вместо терминалки скачивается битый архив размером 309 байт.
0
Файлик протух на сервере. У меня его тоже нет. Удалил.
0
По ссылке «Библиотеки для сборки из сырков.» скачивается ZIP архив, AvL-master.zip, 631 933 байт. Структура вроде целая, не разархивировал.
0
Битый архив я уже удалил. В нем была терминалка от Lifelover'а, послужившая прототипом моей.
0
В смысле не надо было, потому и не разархивировал.
0
Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.