Форум » [x]Harbour » Перехожу с Clipper 5.2e на Harbour, список вопросов от "новичка" » Ответить

Перехожу с Clipper 5.2e на Harbour, список вопросов от "новичка"

Sergy: Добрый день, уважаемые коллеги. Большое спасибо за море справочной информации по переходу, но нужно ещё пнуть меня в нужном направлении. Итак, установил Harbour 3.0 + BCC 5.5.1 ==>> 3.2.0 +minGW скомпилировал и запустил традиционный "Hello, world!" Дело перешло к проекту, из-за которого собственно и речь. Компилируется что через hbmk2, что самим харбором - без ошибок, всего с парой предупреждений, что меня немало удивило. Возникли ошибки на этапе линковки: [more]Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: Unresolved external '_HB_FUN_ENVPARAM' referenced from D:\HB\TRADE100.OBJ Error: Unresolved external '_HB_FUN_INKEYTRAP' referenced from D:\HB\TRADE226.OBJ Error: Unresolved external '_HB_FUN_DISKFREE' referenced from D:\HB\TRADE222.OBJ Error: Unresolved external '_HB_FUN_DISKTOTAL' referenced from D:\HB\TRADE222.OBJ Error: Unresolved external '_HB_FUN_BIOSDATE' referenced from D:\HB\TRADE.OBJ Error: Unresolved external '_HB_FUN_FT_ONTICK' referenced from D:\HB\TRADE.OBJ Error: Unresolved external '_HB_FUN_FT_ONIDLE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_FT_IAMIDLE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_TRAPANYKEY' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_KEYSEND' referenced from D:\HB\TRADE200.OBJ 1) Так понимаю, это ошибки из-за того, что не находятся некоторые функции из активно используемых CT3/Nanforum Toolkit ? Что делать с ними ? Отказываться ? Или есть заменители ? Error: Unresolved external '_HB_FUN_STACKFREE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLILOCUSE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLILOCAVL' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLILOCTOT' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLISTCUSE' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLISTCAVL' referenced from D:\HB\TRADE200.OBJ Error: Unresolved external '_HB_FUN_BLISTCTOT' referenced from D:\HB\TRADE200.OBJ 2) Это - ошибки из-за вызовов встроенных в Blinker функций, без них легко обойтись в принципе... Error: Unresolved external '_HB_FUN_STRNUM2ARRAY' referenced from D:\HB\TRADE208.OBJ Error: Unresolved external '_HB_FUN_CMJS_EXTRACTPARAMS' referenced from D:\HB\TRADE206.OBJ Error: Unresolved external '_HB_FUN_SELECTSTOCKS' referenced from D:\HB\TRADE220.OBJ Error: Unresolved external '_HB_FUN_APPLYSERTCHAGES' referenced from D:\HB\TRADE221.OBJ Error: Unresolved external '_HB_FUN_APPLYCARGOCHAGES' referenced from D:\HB\TRADE221.OBJ Error: Unresolved external '_HB_FUN_APPLYPRICECHAGES' referenced from D:\HB\TRADE221.OBJ 3) А вот это - самое странное - это мои функции, причем некоторые из них вызываются многократно из других модулей. Например ApplyCargoChanges является STATIC в самом модуле TRADE221 - почему линковщик ее не видит, наряду с парой Apply... других ? SelectStocks активно используется в других модулях - но там линкер почему-то ошибок не видит... [/more] Help, please - что делать и куды бечь ?

Ответов - 285, стр: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 All

Dima: Юзай Harbour 3.2 там Hbmk2 чутка умнее и пишет какие библы нужно прилинковать. Хотя может это есть и в 3.0 не знаю так как сразу перелез с 2.0 на 3.2

Sergy: Только вчера поставил Harbour и BCC рядом со старым добрым 5.2e - голова кругом идет... нашел 3.0 - а вот 3.2 где взять ???

Dima: Sergy пишет: голова кругом идет И у меня так было ;) На вскидку не хватает библиотек HBCT , HBNF , прилинкуй их. Если и после этого какие то функции не будут находиться тогда поищи их в ChangeLog.txt или поиском по маске файлов из CONTRIB Все это я делаю (о поиске я) в FAR MANAGER Насчет функций Blinker не знаю ,возможно что то и есть (аналоги) но далеко не все думаю и надо разбираться в каждом отдельном случае. Sergy пишет: а вот 3.2 где взять ??? тут http://clipper.borda.ru/?1-4-0-00000840-000-0-0-1375721378 по линку http://github.com/harbour/core/archive/master.zip


Sergy: HBCT, HBNF указываю жестко в строке компилятора, путь к ним тоже прописан. В каталоге harbour\lib\win\bcc hbct.lib и hbnf.lib точно есть... В папке CONTRIB нашел "непонятные" файлы HBCT.HBC и HBNF.HBC размером по 122 байта каждый - может их куда еще нужно засунуть ?

Dima: Sergy пишет: В папке CONTRIB нашел "непонятные" файлы HBCT.HBC и HBNF.HBC размером по 122 байта каждый - может их куда еще нужно засунуть ? Их и надо линковать вместо HBNF.LIB и HBCT.LIB Совет: юзай HBMK2 и файл проекта HBP Пример (часть почикал) [pre2] C:\hb32mingw\contrib\hbct\hbct.hbc C:\hb32mingw\contrib\hbtip\hbtip.hbc C:\hb32mingw\contrib\xhb\xhb.hbc C:\hb32mingw\contrib\hbnf\hbnf.hbc C:\hb32mingw\contrib\hbmemio\hbmemio.hbc C:\hb32mingw\contrib\gtwvg\gtwvg.hbc C:\hb32mingw\contrib\hbwin\hbwin.hbc C:\hb32mingw\contrib\hbxpp\hbxpp.hbc C:\hb32mingw\contrib\hbmisc\hbmisc.hbc C:\hb32mingw\contrib\rddads\rddads.hbc -lace32 -LC:\MinGW\lib\ -liphlpapi -compr=max -workdir=obj -owinSklad.exe -inc #-mt #-gtwin #-run #-std -gui fix\*.c fix\*.prg cfunc\*.prg .............. sklad.prg rddsys.prg tool\*.prg sklad.rc [/pre2] Собираю все вот таким батником [pre2] set path=C:\MinGW\bin\ c:\hb32mingw\bin\hbmk2 sklad.hbp [/pre2] У тебя он будет свой да и компилятор тоже так как в примере у меня MINGW

SergKis: Sergy пишет:Help, please - что делать и куды бечь ? Такой штукой получите оглавления всех lib: for %%a in ( *.lib ) DO c:\bk8\bcc\bin\TLIB.EXE %%a , %%a.txt Ищите в огл. функции, если найдена подключайте lib к проекту - нет, то вероятно ее придется переписывать.

Sergy: Dima пишет: Их и надо линковать вместо HBNF.LIB и HBCT.LIB Совет: юзай HBMK2 и файл проекта HBP Пример (часть почикал) Большое спасибо за подсказу, сделал так: d:\harbour\contrib\hbnf\hbnf.hbc d:\harbour\contrib\hbct\hbct.hbc -lhbnf -lhbct -LD:\Harbour\lib\win\bcc -workdir=OBJ -otradewin.exe trade.prg trade100.prg trade200.prg trade201.prg trade202.prg ... trade499.prg По сути ничего не поменялось... не находит функций...

Dima: Sergy пишет: -lhbnf -lhbct Это не надо так как выше есть уже HBC А какие функции не находит ?

Sergy: SergKis пишет: Такой штукой получите оглавления всех lib: for %%a in ( *.lib ) DO c:\bk8\bcc\bin\TLIB.EXE %%a , %%a.txt Ищите в огл. функции, если найдена подключайте lib к проекту - нет, то вероятно ее придется переписывать. Спасибо, вот какая интересная петрушка получается с HBNF.LIB: 1) несколько функций изменили свое имя, например: DISKFREE -> DSKFREE, DISKTOTAL -> DSKSIZE... Поставлю условную компиляцию #ifdef __HARBOUR__ ... #endif 2) от части функций придется отказаться, чего уж там... 3) Функция FT_ONTICK точно есть, но возникает ошибка компоновки - как и с моими функциями... сейчас уменьшу кол-во неверных вызовов, посмотрю что да как...

Sergy: Dima пишет: Это не надо так как выше есть уже HBC А какие функции не находит ? Это "системные": Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: Unresolved external '_HB_FUN_SWPRUNCMD' referenced fr Error: Unresolved external '_HB_FUN_ENVPARAM' referenced fro Error: Unresolved external '_HB_FUN_INKEYTRAP' referenced fr Error: Unresolved external '_HB_FUN_DISKFREE' referenced fro Error: Unresolved external '_HB_FUN_DISKTOTAL' referenced fr Error: Unresolved external '_HB_FUN_BIOSDATE' referenced fro Error: Unresolved external '_HB_FUN_FT_ONIDLE' referenced fr Error: Unresolved external '_HB_FUN_TRAPANYKEY' referenced f Error: Unresolved external '_HB_FUN_KEYSEND' referenced from Это - "мои": Error: Unresolved external '_HB_FUN_STRNUM2ARRAY' referenced Error: Unresolved external '_HB_FUN_CMJS_EXTRACTPARAMS' refe Error: Unresolved external '_HB_FUN_SELECTSTOCKS' referenced Error: Unresolved external '_HB_FUN_APPLYSERTCHAGES' referen Error: Unresolved external '_HB_FUN_APPLYCARGOCHAGES' refere Error: Unresolved external '_HB_FUN_APPLYPRICECHAGES' refere

Dima: Sergy пишет: Error: Unresolved external '_HB_FUN_SWPRUNCMD' referenced fr Давай по одной ;) Вместо ее можно юзать hb_processrun EXECANDWAIT WAPI_ShellExecute и что то еще уже не помню ;)

Dima: Sergy пишет: Это - "мои": тебе и карты в руки ! сам же писал.

Sergy: Dima пишет: Давай по одной ;) Вместо ее можно юзать hb_processrun EXECANDWAIT WAPI_ShellExecute и что то еще уже не помню ;) Давай... Подключил HBBLINK, ошибка со SWPRUNCMD ушла. Заменил DISKTOTAL на DSKSIZE - теперь ошибка - не может найти функцию DSKSIZE. По "своим" функциям, разумеется, вопросы будут в последнюю очередь...

Sergy: Вопрос с ENVPARAM решил надыбанным "неизвестно где" исходником: #pragma BEGINDUMP #include <windows.h> #include <tchar.h> #include <stdio.h> #include <hbapi.h> HB_FUNC( ENVPARAM ) { LPTSTR lpszVariable; LPTCH lpvEnv; LPTSTR pszBuffer = NULL; int iLastLen = 0; int pos =0; // Get a pointer to the environment block. lpvEnv = GetEnvironmentStrings(); // If the returned pointer is NULL, exit. if (lpvEnv == NULL) { printf("GetEnvironmentStrings failed (%d)\n", GetLastError()); return ; } // Variable strings are separated by NULL byte, and the block is // terminated by a NULL byte. lpszVariable = (LPTSTR) lpvEnv; while (*lpszVariable) { int iLen = lstrlen( lpszVariable ); pszBuffer = realloc( pszBuffer, iLastLen + iLen + 2 ); memcpy( pszBuffer+iLastLen, lpszVariable, iLen ); memcpy( pszBuffer+iLastLen+iLen, "\r\n", 2 ); iLastLen += iLen + 2; lpszVariable += lstrlen(lpszVariable) + 1; } FreeEnvironmentStrings(lpvEnv); hb_retc( pszBuffer ); } #pragma ENDDUMP соотв. остаются: Turbo Incremental Link 5.00 Copyright (c) 1997, 2000 Borland Error: Unresolved external '_HB_FUN_INKEYTRAP' referenced fr Error: Unresolved external '_HB_FUN_DSKFREE' referenced from Error: Unresolved external '_HB_FUN_DSKSIZE' referenced from Error: Unresolved external '_HB_FUN_BIOSDATE' referenced fro Error: Unresolved external '_HB_FUN_FT_ONIDLE' referenced fr Error: Unresolved external '_HB_FUN_TRAPANYKEY' referenced f Error: Unresolved external '_HB_FUN_KEYSEND' referenced from

Dima: Dima пишет: поищи их в ChangeLog.txt а так же поиском на форуме

Sergy: Dima пишет: поищи их в ChangeLog.txt а так же поиском на форуме Бинго! Так разобрался с DISKFREE и DISKTOTAL - оказывается, они заменяются на вызовы HB_DISKSPACE(d, HB_DISK_FREE) и тп. При помощи условной компиляции пока отказался от некоторых системных функций. Со своими функциями походу тоже ясно - ошибка с длинными именами - Clipper все что длинее 10 знаков игнорирует, а тут - строго...

Sergy: Запустил ! Разобрался с кодовой страницей, убрал вызов FILESMAX() Вопрос: Использую NTX, в некоторых редких случаях требуется, чтoбы вместо расширений *.DBF и *.NTX были немного другие, напрмер: *.XDB, *.XNT - так я отличаю "архивные" таблицы и действующие, чтобы их не копировать при бэкапе. Harbour этого не любит ? Вылетает: Unrecoverable error 9108: hb_ntxIndexUnLockRead: unlock error. Вот на таком коде: USE (cDir+cAlias+cExt) INDEX (cDir+cAlias+cNtx) READONLY NEW

Andrey: Sergy пишет: Error: Unresolved external '_HB_FUN_KEYSEND' referenced from Это CT.LIB Я отказался от неё.

Dima: Andrey пишет: Я отказался от неё. и я Sergy пишет: Использую NTX Тяжелый случай. Тяжело и громоздко. Не надо его юзать. CDX самое то или IDX (CDX) под ADS или LetoDB (CDX) Dima пишет: CDX самое то Но там могут быть свои приколы.

Dima: Sergy пишет: (cDir+cAlias+cExt) Выведи это дело в ? cDir+cAlias+cExt и глянь что кажет , возможно твой косяк

Sergy: Andrey пишет: Это CT.LIB Я отказался от неё. Понятно, что у виндовой программы и расширенного Harbour всяко функций больше. Но сейчас нужно запустить проект и посмотреть, где что да как. Dima пишет: Тяжелый случай. Тяжело и громоздко. Не надо его юзать. CDX самое то или IDX (CDX) под ADS или LetoDB (CDX) Переделывать NTX на CDX или еще дальше - SQL подобные БД вообще думаю пока нет смысла, когда программа "еле дышит"... Запустить, попробовать, добиться хотя-бы такого-же функционала, как и с 5,2е, обкатать, а потом уж оптимзировать. Такие вот мысли пока...

Dima: Sergy пишет: Запустить, попробовать, добиться хотя-бы такого-же функционала, как и с 5,2е, обкатать, а потом уж оптимзировать. Все правильно. Так и я думал и все получилось и у тебя все будет нормально с переводом. Просто остынь и осмысли А вопросы сюда ;) Поможем ! ЗЫ Я тоже не верил что смогу перевести довольно большую прогу с Clipper 5.2 на Harbor , но.......5 дней упорной работы и добился такого же функционала 5 метров исходников , 300 файлов , пришлось попотеть конечно. Руки не опускай и все будет норм ! По ходу косяков будет много по началу но со временем все меньше и меньше. Просто поверь.

Sergy: Dima пишет: Выведи это дело в ? cDir+cAlias+cExt и глянь что кажет , возможно твой косяк Мой. удалил клипперовские *.NTX, а - *.XNT - остались... Удалил, перестроились ок. Сорри.

Sergy: Dima пишет: Все правильно. Так и я думал и все получилось и у тебя все будет нормально с переводом. Просто остынь и осмысли А вопросы сюда ;) Поможем ! А вот за это - отдельное БОЛЬШОЕ Спасибо! ЗЫ Я тоже не верил что смогу перевести довольно большую прогу с Clipper 5.2 на Harbor , но.......5 дней упорной работы и добился такого же функционала 5 метров исходников , 300 файлов , пришлось попотеть конечно. Руки не опускай и все будет норм ! По ходу косяков будет много по началу но со временем все меньше и меньше. Просто поверь. У меня чуть скромнее: 34 файла, 2,5 мега исходников. Всегда старался не пользоваться никакими сторонними библиотеками, кроме стандартных Nanforun Toolkit и Clipper Tools - подозревал, что этот день когда-нить настанет... В первом приближении - Работает!!! И ТАК БЫСТРО, что ппц.

Sergy: Итак, огромное спасибо всем помощникам! Программа запустилась и очень шустро (по сравнению с ntvdm) работает. Возникающие то тут, то там вопросы - решаемы, связаны с вольностями Clipper - все, что дальше десятого символа считается неважным. На повестке дня пока два насущных вопроса, связанных с отказом от нескольких системных функций: 1) В программе есть возможность записи клавиатурных нажатий. Типа макросов. И последующего их воспроизведения одним нажатием для автоматизации рутинных операций. Раньше это было организовано при помощи INKEYTRAP/TRAPANYKEY/KEYSEND. Одна из этих функций актвивизировалась и складывала в фоновом режиме все нажатия юзера в массив/строку. После чего в любой момент из массива/строки при помощи KEYSEND эти коды кнопок передавались в буфер клавиатуры. Просто и удобно. Как можно релизовать похожий механизм в Harbour ? 2) Нужен аналог функции BIOSDATE(), она используется сами понимаете для чего. Отказываться полностью не хочется, а использовать что-либо взамен - придется бегать по всем машинам с флэшкой, переделывать ключевые файлы.

Dima: Sergy пишет: Нужен аналог функции BIOSDATE() [pre2] Func Biosdate() #include "hbwin.ch" return GetRegistry( WIN_HKEY_LOCAL_MACHINE,"HARDWARE\DESCRIPTION\System" ,"SystemBiosDate" ) [/pre2]

Sergy: Dima пишет: Func Biosdate() #include "hbwin.ch" return GetRegistry( WIN_HKEY_LOCAL_MACHINE,"HARDWARE\DESCRIPTION\System" ,"SystemBiosDate" ) Спасибо, использую

Dima: Sergy Можно еще к MAC адресу сетевой прицепиться.

Sergy: Dima пишет: Можно еще к MAC адресу сетевой прицепиться. Безусловно, только сейчас первая задача - сохранить и перенести функционал. И только потом развиваться дальше. Вот с клавиатурными нажатиями - с какой стороны подступить ?

Dima: Sergy пишет: Вот с клавиатурными нажатиями - с какой стороны подступить ? Можно попробовать FT_OnTick({|| test()},1) в функции Test и пробуй записывать Или ваять самому https://groups.google.com/forum/#!topic/comp.lang.xharbour/e77vVVb1Kuc

Sergy: Dima пишет: Можно попробовать FT_OnTick({|| test()},1) в функции Test и пробуй записывать Или ваять самому https://groups.google.com/forum/#!topic/comp.lang.xharbour/e77vVVb1Kuc Буду пробовать...

Sergy: Dima пишет: Func Biosdate() #include "hbwin.ch" return GetRegistry( WIN_HKEY_LOCAL_MACHINE,"HARDWARE\DESCRIPTION\System" ,"SystemBiosDate" ) Error: Unresolved external '_HB_FUN_GETREGISTRY' referenced from... хотя в проект hbwin.hbc подключил...

Dima: Sergy пишет: Error: Unresolved external '_HB_FUN_GETREGISTRY' referenced from. попробуй win_regGet() У меня Harbour 3.2 у тебя 3.0 вот и отличия ЗЫ Можно еще сырец глянуть win_reg.prg из Hbwin

Sergy: Dima пишет: попробуй win_regGet() У меня Harbour 3.2 у тебя 3.0 вот и отличия Получилось.

Sergy: Заметил, что ACHOICE себя как-то странно ведет. Суть: REPEAT pos := ACHOICE(2,10,2,40,show_array,,,pos) UNTIL (LastKey() == K_ENTER) Да, весь массив в Clipper прокручивается в одной строке - так выбираю логин входящего юзера, чтобы не вводить с клавиатуры. Компактно и поиск по первой букве работает. Плюс стрелками можно выбрать: Savin -> Serebrov -> Silaev... В Harbour при нажатии "стрелка вверх" неожиданно появляется второй элемент массива на третьей строке, т.е. там, где ACHOICE делать вообще нечего... Залез в tests\ac_test.prg /* * $Id: ac_test.prg 16875 2011-06-14 20:10:06Z vszakats $ */ *+==================================================================== *+ *+ Source Module => ac_test.prg *+ *+ Released to Public Domain. *+ *+ Functions: Procedure test() *+ Function cUserFunction() *+ *+ Tables: use vendor exclusive *+ *+ Reformatted by Click! 1.10 on Aug-13-1997 at 11:39 pm *+ *+==================================================================== #include "achoice.ch" #include "inkey.ch" *+-------------------------------------------------------------------- *+ *+ Procedure test() *+ *+-------------------------------------------------------------------- *+ procedure main() local aPrompts := {; "AGRI-PLANTS" ,; "ALAN R. SMITH GREENHOUSES" ,; "ALLAN MURRAY NURSERY, INC." ,; "APOPKA FOREST" ,; "LIGHT HOUSE NURSERIES" ,; "BAUCOM'S" ,; "BAY HILL NURSERY, INC." ,; "BAYWOOD NURSERIES" ,; "BIG OAK NURSERY" ,; "C & N NURSERY" ,; "CHARLES QUALITY PLANTS" ,; "CONNELL FARMS" ,; "DEWAR NURSERIES, INC." ,; "DIAMOND T NURSERY" ,; "DISTINCTIVE PALMS NURSERIES" ,; "DONKAY NURSERY" ,; "DOUG INGRAM & SONS NURSERY" ,; "DRIFTWOOD GARDENS, INC." ,; "ELVA PLANT NURSERY, INC." ,; "ERINON" ,; "EVANS NURSERY" ,; "FANCY PLANTS" ,; "FL.PLANT GROWERSCOOP" ,; "FLORIDA CACTUS INC." ,; "FLOWERING TREE GROWERS, INC." ,; "FLOWERWOOD NURSERY" ,; "FOLIAGE FACTORY TOO" ,; "GATOR GROWERS NURSERY, INC." ,; "GAZEBO LANDSCAPE DESIGN, INC." ,; "GEM ORNAMENTALS" ,; "GRANNY'S GARDEN" ,; "GRAY'S ORNAMENTALS" ,; "GREEN MASTERS INC." ,; "GREEN MEADOW NURSERY" ,; "PIXLEY'S PLANT PLACE" ,; "HARRISON'S NURSERY, INC." ,; "G & G FOLIAGE" ,; "IVEY'S NURSERY, INC." ,; "JB NURSERIES, INC." ,; "JON'S NURSERY" ,; "JONES & JONES NURSERY, INC." ,; "KAGER'S NURSERY" ,; "KIRKLAND'S NURSERY" ,; "LAND OF BROMELIADS" ,; "LANDSCAPE NURSERY, INC." ,; "LIEWALD'S NURSERY INC." ,; "LLOYD & RINGS NURSERY" ,; "LONG VAN DOUNG" ,; "MAPEL'S LANDSCAPE NURSERY" ,; "MILESTONE AGRICULTURE, INC." ,; "MOJICA NURSERY & FRUITS" ,; "NELSON'S ROSES" ,; "PARK GARDENS" ,; "PAUL LUKAS INC." ,; "PECKETT'S INC." ,; "PENANG NURSERY, INC." ,; "PINES III NURERIES" ,; "PINEVIEW NURSERY" ,; "POUL JENSEN NURSERY" ,; "R.P. WELKER" ,; "RICHARD ROGERS NURSERY, INC." ,; "SPRING HILL NURSERY" ,; "T.O. MAHAFFEY, JR." ,; "TUCKER NURSERY" ,; "TURTLE POND NURSERY" ,; "TUTTLE'S NURSERY INC." ,; "VALLEY CACTUS" ,; "WHISPER WINDS, INC." ,; "WHITE ROSE NURSERIES INC." ,; "WOODWAY" ,; "FLORI-DESIGN" ,; "GREEN ACRES FOLIAGE, INC" ,; "FLORAL EXPO" ,; "TORRES NURSERY" ,; "DARRYL KOON" ,; "TRISTAR NURSERY" ,; "KAY WEST NURSERY" ,; "JAYMAR NURSERY" ,; "J D F LANDSCAPE NURSERY" ,; "DEROOSE PLANTS, INC." ,; "THE TREEHOUSE" ,; "COSTELLO'S ARECAS, INC." ,; "FLORICO FOLIAGE" ,; "THE NATIVES" ,; "GREENS NURSERY" ,; "STEWART NURSERIES" ,; "G & T FOLIAGE, INC." ,; "GOOD TIMES NURSERY" ,; "CONCEPTS IN GREENERY, INC." ,; "DUNN BROTHERS CITRUS, INC." ,; "JOHN PLANK GREENHOUSES" ,; "GREENER PASTURES NURSERY" ,; "MULVEHILL NURSERY" ,; "A NU LEAF" ,; "IVY DESIGNS, INC." ,; "B & C TROPICALS" ,; "SPANISH RIVER NURSERY, INC." ,; "JACK CHRISTMAS & ASSOCIATES" ,; "SPECIALIST GROWERS" ,; "HOMRICH NURSERY, INC." ,; "COUNTRYSIDE FOLIAGE, INC." ,; "RFJ COMPANY" ,; "LAKE BRANTLEY PLANT CORP." ,; "MARISTYME" ,; "MERISTEM NURSERY, INC." ,; "TROPIC DECOR - EARL WILSON" ,; "URQUHART'S NURSERY" ,; "ACE PLANT NURSERY" ,; "HATTAWAYS GREENHOUSE, INC." ,; "Florida Plant Growers" ,; "Junior Nursery" ,; "Fox's Nurseries, Inc." ,; "Vaughan Nursery" ,; "MERRYGRO FARMS" ,; "ALL SEASONS NURSERY" ,; "BENCHMARK FOLIAGE" ,; "SAMMY'S NURSERY" ,; "SUNSHINE GROWERS" ,; "Blooming-Fields Nursery" } local aPermits := {} local x local nChoice local ncntr clear screen setcolor( 'GB+/B,GR+/R,,,W/N' ) SET CURSOR ON asize( aPermits, Len( aPrompts ) ) for x := 1 to Len( aPrompts ) aPermits[ x ] := !( 'V' $ aPrompts[ x ] ) next #define TEST1 #ifdef TEST1 for ncntr := 1 to 17 aPermits[ nCntr ] := .F. aPermits[ Len( aPrompts ) - nCntr + 1 ] := .F. next aPermits[ 32 ] := .F. aPermits[ 33 ] := .F. aPermits[ 34 ] := .F. #endif nChoice := achoice( 5, 10, 20, 70, aPrompts, aPermits, "cUserFunction" ) setpos( 0, 0 ) * clear screen ? nChoice if nChoice > 0 ? aPrompts[ nChoice ] endif setpos( maxrow() - 2, 0 ) return *+-------------------------------------------------------------------- *+ *+ Function cUserFunction() *+ *+-------------------------------------------------------------------- *+ function cUserFunction( nMode, nCurElement, nRowPos ) local nRetVal := AC_CONT // Default, Continue local nKey := lastkey() local nRow := Row() local nCol := Col() HB_SYMBOL_UNUSED( nRowPos ) @ 0, 20 SAY Str( nRow, 3 ) + " " + Str( nCol, 3 ) do case // After all pending keys are processed, display message case nMode == AC_IDLE @ 0, 0 say padr( ltrim( str( nCurElement ) ), 10 ) nRetVal := AC_CONT // Continue ACHOICE() case nMode == AC_HITTOP // Attempt to go past Top @ 0, 0 say "Hit Top " // tone( 100, 3 ) case nMode == AC_HITBOTTOM // Attempt to go past Bottom @ 0, 0 say "Hit Bottom" // tone( 100, 3 ) case nMode == AC_EXCEPT // Key Exception @ 0, 0 say "Exception " do case case nKey == K_RETURN // If RETURN key, select nRetVal := AC_SELECT case nKey == K_ESC // If ESCAPE key, abort nRetVal := AC_ABORT otherwise nRetVal := AC_GOTO // Otherwise, go to item endcase endcase return nRetVal Запустил, офигел: У всех так ? Второй файл, ac_test2 тоже работает через Ж...

Andrey: Sergy пишет: Заметил, что ACHOICE себя как-то странно ведет. Да, он от клипера отличается. Смотри доку и переделывай обработку функций ACHOICE, MEMOEDIT, TBROWSE. Мне тоже пришлось это переделывать. Разницу сейчас не скажу, но делал маленькие тестовые примеры, а потом код перетаскивал в свои системы.

Sergy: Andrey пишет: Смотри доку Какую именно доку ?

Andrey: Sergy пишет: Какую именно доку ? http://clipper.borda.ru/?1-6-0-00000007-000-0-0-1365407210 http://clipper.borda.ru/?1-6-0-00000004-000-0-0-1355750592 и т.д.

Sergy: Andrey пишет: http://clipper.borda.ru/?1-6-0-00000007-000-0-0-1365407210 http://clipper.borda.ru/?1-6-0-00000004-000-0-0-1355750592 и т.д. Вот смотрю конкретно ACHOICE: http://www.elektrosoft.it/tutorials/Harbour-Reference-Guide/harbour-reference-guide.htm#AChoice Не могу понять - какие в нем отличия от Клипперовского ? Ведь заявлена полная совместимость, а по сути получается, что просто криво реализована? Может у меня сборка такая, раз даже тестовый пример не работает...

PSP: Да, с AChoice косяк есть... Хех... В тех исходниках, что у меня (а они довольно старые, от 30.01.2013), в achoice.prg увидел следующее: [pre2]/* TOFIX: --- #include "inkey.ch" CLS hb_keyPut( { K_DOWN, K_UP } ) // bogus '2' appears out of the area here. AChoice( 0, 0, 0, 0, { "1", "2" } ) --- */ [/pre2] Так что баг уже давно замечен. Осталось, чтобы кто-то его вылечил... ))) У кого есть свежие исходники? Там не исправлено еще? update: Сечас посмотрел на git. Не исправлено... ((( Ну что ж, либо забить, либо искать косяк в achoice.prg и исправлять.

azoo: По inkeytrap() см. ветку http://clipper.borda.ru/?1-4-0-00000853-000-0-0-1369379704

Sergy: azoo пишет: По inkeytrap() см. ветку Спасибо. Пригодилось.

Sergy: Не получается подружить русский язык и файловую систему. Например: [pre2] FUNC Main() REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU866 HB_LANGSELECT("RU866") HB_CDPSELECT("RU866") ? File("текст.!") QUIT RETURN [/pre2] Всегда дает результат .F. Файл разумеется есть, лежит рядом с exe. Если переименовать в латиницу - результат File("text.!") сразу .T. Команда RUN("@echo --- Привет --- ") дает кракозябры на экране. В hbp указал -DHB_LANG_DEFAULT=RU866 -DHB_CODEPAGE_DEFAULT=RU866 Что я еще забыл переключить в настройках ?

Pasha: Есть 2 способа решения этого вопроса: 1. Транслировать имена файлов из cp866 в cp1251 2. Добавить в конец модуля такую функцию: #pragma BEGINDUMP #include "windows.h" HB_FUNC_STATIC( SETFILEAPIS ) // Имена файлов в кодировке OEM { SetFileApisToOEM(); } #pragma ENDDUMP и вызвать ее при старте программы

Sergy: Pasha пишет: Есть 2 способа решения этого вопроса: 1. Транслировать имена файлов из cp866 в cp1251 Переделывать всю программу, искать вызовы файловых функций (а там во всех местах - и FILE() и DIRECTORY() и тд и тп) ... муторно очень... 2. Добавить в конец модуля такую функцию: Добавил. RUN("@echo --- Привет ---") теперь пишет нормально, а File() все равно дает .F.

Sergy: Попробовал даже так: sx := "абв.dbf" sx := HB_TRANSLATE(sx,"RU866","RU1251") ? File(sx) все равно дает .F.

Andrey: Попробуй так: FUNC Main() REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU866 HB_LANGSELECT("RU866") HB_CDPSELECT("RU866") sx := "абв.dbf" sx := HB_ANSITOOEM(sx) ? File(sx)

Sergy: Andrey пишет: Попробуй так: ... sx := HB_ANSITOOEM(sx) Попробовал. FALSE Поставил наоборот - HB_OEMTOANSI(sx) - заработало. Блин... этож сколько переписывать придется... просто ппц... Неужели нет вариантов ???

Петр: Sergy пишет: Блин... этож сколько переписывать придется... просто ппц... Неужели нет вариантов ??? Лично у меня FUNC Main() REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU866 HB_LANGSELECT("RU866") HB_CDPSELECT("RU866") ? File("текст.!") QUIT RETURN показало .T. если исходник в 866 странице, ну и .F. если в 1251

Sergy: Исходник ведь клипперовский, конечно он в 866 странице... Базы данных, все сообщения - все работает нормально. А вот с файловой системой какая-то непонятка...

Петр: А какая ось, как запускаете программу, что показывает chcp?

Sergy: Петр пишет: А какая ось, как запускаете программу, что показывает chcp? На домашнем компе - XP, запускаю программу из под Far, chcp показывает 866 На работе - сервер 2003 SR3, остальное тоже самое - и из под Far и из проводника тоже самое...

Петр: Ну не знаю, Win 7, Far 3.0 build 3249, active code page 866 .T.

petr707: proc main Local cfname // set name before SetFileApis - wrong cfname:="тест.!" strfile("1",cfname,.f.) ? file(cfname) SetFileApis() ? file(cfname) inkey(100) // set name after SetFileApis - right cfname:="тест.!" strfile("2",cfname,.f.) ? file(cfname) return #pragma BEGINDUMP #include "windows.h" HB_FUNC_STATIC( SETFILEAPIS ) // { SetFileApisToOEM(); } #pragma ENDDUMP

Sergy: Петр пишет: Ну не знаю, Win 7, Far 3.0 build 3249, active code page 866 .T.

Sergy: petr707 пишет: proc main Local cfname // set name before SetFileApis - wrong cfname:="тест.!" strfile("1",cfname,.f.) ? file(cfname) SetFileApis() ? file(cfname) inkey(100) // set name after SetFileApis - right cfname:="тест.!" strfile("2",cfname,.f.) ? file(cfname) return #pragma BEGINDUMP #include "windows.h" HB_FUNC_STATIC( SETFILEAPIS ) // { SetFileApisToOEM(); } #pragma ENDDUMP Прикольно. У меня получилось .T. .T. .T. НО имя файла в?бв.! Компилировал припомощи hbp следующего содержания (скопирован с проекта) d:\harbour\contrib\hbnf\hbnf.hbc d:\harbour\contrib\hbct\hbct.hbc d:\harbour\contrib\hbwin\hbwin.hbc d:\harbour\contrib\hbblink\hbblink.hbc -lhbcpage.lib -inc -run -LD:\Harbour\lib\win\bcc -DHB_LANG_DEFAULT=RU866 -DHB_CODEPAGE_DEFAULT=RU866 -prgflag=/v lang_test2.prg Ваще ниче не понимаю...

petr707: Удалите все файлы, и перезапустите ,старый Ваш файл тест.! картинку портит Должно быть два файла в?бв.! ( содержимое="1") и тест.! (содержимое="2") proc main REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU866 HB_LANGSELECT("RU866") HB_CDPSELECT("RU866") // set name before SetFileApis - wrong cfname:="тест.!" strfile("1",cfname,.f.) ? file(cfname) SetFileApis() ? file(cfname) inkey(100) // set name after SetFileApis - right cfname:="тест.!" strfile("2",cfname,.f.) ? file(cfname) return #pragma BEGINDUMP #include "windows.h" HB_FUNC_STATIC( SETFILEAPIS ) // { SetFileApisToOEM(); } #pragma ENDDUMP

Sergy: Вот такой пример: proc main Local cfname // set name before SetFileApis - wrong cfname:="тест1.!" strfile("1",cfname) ? file(cfname) SetFileApis() // set name after SetFileApis - right cfname:="тест2.!" strfile("2",cfname) ? file(cfname) return #pragma BEGINDUMP #include "windows.h" HB_FUNC_STATIC( SETFILEAPIS ) // { SetFileApisToOEM(); } #pragma ENDDUMP дает .T. .T. и два файла: в?бв1.! и в?бв2.!

Sergy: почти синхронно ответили... ща попробую Ваш пример

petr707: Не работает SetFileApis()

Sergy: petr707 пишет: Удалите все файлы, и перезапустите ,старый Ваш файл тест.! картинку портит Должно быть два файла в?бв.! ( содержимое="1") и тест.! (содержимое="2") Все удалил получил две шутки TRUE и ОДИН файл в?бв.! с содержимым 2

Sergy: petr707 пишет: Не работает SetFileApis() Он работает, но как-то "не до конца". Без него RUN("@echo -- Привет --") дает кракозябры. С ним - всё нормально.

petr707: Запуск test.exe //info -что показывает ?

Sergy: petr707 пишет: Запуск test.exe //info -что показывает ? Harbour Terminal: Windows native console Harbour 3.0.0 (Rev. 16951) Windows XP 5.1.2600 Service Pack 3 DS avail=1692828KB OS avail=2079244KB EMM avail=0KB MemStat:Off MT:Off .T. .T. .T.

petr707: RUN("@echo -- Привет --") дает кракозябры еще раз проверяем кодовую страницу PRG -файла

Sergy: petr707 пишет: еще раз проверяем кодовую страницу PRG -файла Вот ascii-коды символов, входящих в слово "Привет", которые выводит встроенный редактор FAR: 143 224 168 162 165 226

petr707: Чтобы не зависеть от кодовой страницы Prg-файла замените cfname:="тест.!" на cfname:=CHR(226)+CHR(165)+...//"тест.!"

Sergy: petr707 пишет: Чтобы не зависеть от кодовой страницы Prg-файла замените cfname:="тест.!" на cfname:=CHR(226)+CHR(165)+...//"тест.!" сделал. результат не изменился. три штуки TRUE один файл с именем в кракозябрах с содержимым "2"

petr707: Начинаем "шаманить" После строки HB_CDPSELECT("RU866") Добавляем одну строку HB_GtInfo(HB_GTI_CODEPAGE, 255) // oem_charset //HB_GtInfo(HB_GTI_CODEPAGE, 0 ) // ansi_charset // HB_SETTERMCP("RU256")//, "RU1251", .t. )

Sergy: petr707 пишет: Начинаем "шаманить" После строки HB_CDPSELECT("RU866") Добавляем одну строку HB_GtInfo(HB_GTI_CODEPAGE, 255) // oem_charset ┌────────────────────────────────────────────┐ │ Error BASE/1003 Переменная не существует: │ │ HB_GTI_CODEPAGE │ │ │ │ Quit Retry │ └────────────────────────────────────────────┘ Подключил hbgtinfo.ch результат - один в один - три TRUE, один файл с названием из кракозябр и содерджимым 2 Поставил HB_GtInfo(HB_GTI_CODEPAGE, 0) - тоже самое

petr707: Похоже дело не в русских именах файлов а вообще с кодовой страницей Предлагаю скомпилировать и выполнить тесты из \hb30\tests\ можно начать с gtchars.prg

Sergy: petr707 пишет: можно начать с gtchars.prg скомпилировал, боксики-квадратики видны ok

Sergy: вместо польских поставил RU866, вроде все работает: Или я чего не понимаю ?

Sergy: Вот что нашел тут: http://msdn.microsoft.com/en-us/library/windows/desktop/aa365534(v=vs.85).aspx 8-bit console apps using the OEM codepage Note: If you are writing/porting an 8-bit console application, in addition to calling SetFileApisToOem() you should also call setlocale(LC_ALL, ".OCP") followed by _setmbcp(_MB_CP_LOCALE). Может этих двух вызовов и не хватает?

Sergy: Помогите плиз...

Dima: XP SP2 Текст в DOS кодировке (набирался в FAR) Harbour 3.2.0dev (Rev. 18899) [pre2] FUNC Main() REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU866 HB_LANGSELECT("RU866") HB_CDPSELECT("RU866") fclose(fcreate("текст.!")) ? File("текст.!") // .T. RUN("@echo -- Привет --") // и тут все норм на экране QUIT RETURN [/pre2]

Sergy: Dima пишет: Harbour 3.2.0dev я бился и так и эдак - походу дело в версии Harbour. Нужно пробовать 3.2 вместо 3.0. Подскажите плиз - с чего начать. Там так понимаю, все идет в исходниках, нужно саму систему сначала скомпилить...

Dima: Sergy Сливай , распаковывай и собирай http://github.com/harbour/core/archive/master.zip

Pasha: Sergy пишет: Помогите плиз... Действительно, необходимо использовать Harbour 3.2 Это уникодная сборка, а 3.0 - еще не уникодная. 3.2 преобразует имена файлов в UNICODE, и проблем с именами не возникнет, если указана cp866 Вызов SetFileApis в этом случае не нужен.

Sergy: Pasha пишет: Действительно, необходимо использовать Harbour 3.2 Это уникодная сборка, а 3.0 - еще не уникодная. 3.2 преобразует имена файлов в UNICODE, и проблем с именами не возникнет, если указана cp866 Вызов SetFileApis в этом случае не нужен. Все заработало как нужно. Правда EXE стал вместо 2,5 мегов почти 4 - но кого это сегодня заботит... Уважаемые старожилы - предупреждайте новичков о таких вилах, спрятанных в стоге сена по названием Harbour 3.0. Спасибо за поддержку и помощь.

Sergy: Dima пишет: Сливай , распаковывай и собирай http://github.com/harbour/core/archive/master.zip Видимо "мой кунг-фу недостаточно хорош..." (с) Слил отсюда: https://github.com/harbour/core готовый EXE для Windows - все запустилось. Какие отрицательные последствия от такого упрощенного шага? Девелопер Харбора из меня вряд-ли пока получится...

Dima: Sergy пишет: Правда EXE стал вместо 2,5 мегов почти 4 А ты его сожми UPX В файле проекта пропиши -compr=max

Sergy: Dima пишет: А ты его сожми UPX В файле проекта пропиши -compr=max да, тоже мысль. Кстати, или мне чудится на радостях после вчерашней бессонной ночи, или этот EXE стал ЕЩЕ ШУСТРЕЕ (компилер и комп разумеется те-же самые, что и вчера) ? Такое возможно ?

Sergy: Dima пишет: А ты его сожми UPX В файле проекта пропиши -compr=max Попробовал. Так, для общей инфы: В файле ресурса есть пяток иконок (кому какие понравятся, на выбор взамен старой). Система их не видит в сжатом EXE. Т.е. в диалоге ярлыка "сменить иконку" только один вариант - тот, что был первым в списке.

Dima: Sergy пишет: Так, для общей инфы: В файле ресурса есть пяток иконок (кому какие понравятся, на выбор взамен старой). Система их не видит в сжатом EXE. Т.е. в диалоге ярлыка "сменить иконку" только один вариант - тот, что был первым в списке. Так вот он в чем косяк оказывается. Это ответ на мой вопрос тут http://clipper.borda.ru/?1-4-0-00000881-000-0-0-1375200620

Sergy: Dima пишет: Так вот он в чем косяк оказывается. Это ответ на мой вопрос тут http://clipper.borda.ru/?1-4-0-00000881-000-0-0-1375200620 Наверняка. Можно будет попробовать другие уровни сжатия - может быть при каком-то из них (не -max) ресурсы будут доступны извне программы.

Dima: Sergy пишет: Можно будет попробовать другие уровни сжатия Уже. Результат тот же. Вот и думаю теперь а есть ли смысл паковать EXE. В чистом виде весит 7.3 метра , в упакованном 2.2 метра и запускается по сети.

Sergy: а запуск "по сети" у кого быстрее - у упакованного или у обычного ? если разницы нет - какой тогда смысл паковки ? И еще: при запуске "по сети" что показывает EXEPATH() ?

Pasha: Если так беспокоит размер exe, то почему бы не использовать сборку с harbour*.dll ? exe сразу же станут фантастически маленькими.

Dima: Pasha пишет: почему бы не использовать сборку с harbour*.dll ? Это опция hbmk2 ?

Pasha: Dima пишет: Это опция hbmk2 ? Да, опция -shared Можно использовать не только harbour*.dll, а и прочие библиотеки как dll, но это уже надо указывать ручками: заменить -lhbct на -lhbct-bcc и так далее Конечно, в целом программа меньше не станет. С учетом dll она станет больше. Но зато обновлять ее будет не в пример удобнее.

Dima: Pasha Спасибо !

Sergy: Возник вопрос: при включенной русской раскладке "точка" на цифровой клавиатуре неожиданно стала "запятой". Мне понятно, что это по дефолту установлено в винде, но юзеры бесятся. Есть ли красивый выход из этой ситуции ?

Dima: Sergy пишет: Возник вопрос: при включенной русской раскладке "точка" на цифровой клавиатуре неожиданно стала "запятой". Точно ,есть такой косяк.

Sergy: Dima пишет: Точно ,есть такой косяк. Пока в первом приближении такая мысль: поставить SETKEY() на "запятую" и анализировать текущее GET-поле. Если его тип равен N - посылать в буфер клавиатуры CHR(8) и "точку"

Dima: Sergy Это не первый косяк такого рода в этом терминале и если не ошибаюсь в прошлый раз косяк исправил Павел.

Sergy: Dima пишет: Это не первый косяк такого рода в этом терминале и если не ошибаюсь в прошлый раз косяк исправил Павел. Дабы дважды не наступать на одни и те-же грабли - подскажи плиз - что за косяк и какое решение ? Спасибо.

Dima: Dima пишет: анализировать текущее GET-поле Анализировать надо и еще Procname (в цикле) мне кажется.

Dima: Sergy пишет: что за косяк и какое решение Был косяк с какой то буквой кажется не помню какой то ли ё то ли еще какой. И он пофиксен.

Sergy: Dima пишет: И он пофиксен. где ? как именно ?

Dima: Sergy пишет: где ? как именно ? Паша придет скажет я не помню ;)

Sergy: Есть ли способ проверить существование текущего GET-объекта ? Чтобы потом сделать проверку наподобие такой: VALTYPE(oGet:varGet() == "N") ?

Dima: Sergy пишет: Есть ли способ проверить существование текущего GET-объекта ? а зачем если ты объявишь Set key (46 код) на эту педаль и будешь слать в буфер точку ?

Sergy: Dima пишет: а зачем если ты объявишь Set key (46 код) на эту педаль и будешь слать в буфер точку ? а если там текстовое поле и нужна запятая ?

Dima: Sergy Если мы говорим о цифровой панели и о кнопке DEL c точкой , то при нажатии этой педали всегда должна биться точка если включен NumLock не зависимо от раскладки клавы. Или я что то не понял ? :)

Sergy: Dima пишет: Если мы говорим о цифровой панели и о кнопке DEL c точкой , то при нажатии этой педали всегда должна биться точка если включен NumLock не зависимо от раскладки клавы. Или я что то не понял ? :) Да, именно о ней. Но разве INKEY() этой запятой чем-то отличается от запятой, набранной на стандартной клавиатуре? Ведь иногда нужна именно запятая. ... пойду проверю... upd: не отличаются. И в том и другом случае код 44. Эти кнопки, кстати о птичках, легко отличал TRAPANYKEY() И на его основе (кроме макросов), такая замена была-бы сделана в три строчки кода...

Dima: Sergy пишет: Есть ли способ проверить существование текущего GET-объекта ? Чтобы потом сделать проверку наподобие такой: VALTYPE(oGet:varGet() == "N") ? Ваял что то ваял я , смотри как можно проанализировать но есть затык [pre2] Proc Main local acc:=0 local acc1:=" " cls setmode(25,80) set key 28 to test @ 0,0 get acc @ 1,0 get acc1 read RETURN ************ FUNCTION test() LOCAL n := 0 ,i WHILE ! Empty( ProcName( n ) ) n++ if procname(n)=="HBGETLIST:READMODAL" for i=1 to len(__GETLISTACTIVE()) ? __GETLISTACTIVE()[ i ],i * вот тут можно проверять по идее Valtype(__GETLISTACTIVE()[13]) твоя текущая переменная в GET * но зараза все время выдает "C" , похоже не там копаю или не так........ next endif ENDDO RETURN NIL [/pre2]

Dima: Все разобрался Функция Test [pre2] FUNCTION test() LOCAL n := 0 ,i WHILE ! Empty( ProcName( n ) ) n++ if procname(n)=="HBGETLIST:READMODAL" if valtype(GetActive():varGet())=="N" hb_keyins(".") exit endif endif ENDDO RETURN NIL [/pre2] Упрощаем ;) [pre2] FUNCTION test() if GetActive()#NIL if valtype(GetActive():varGet())=="N" hb_keyins(".") endif endif return nil [/pre2] ЗЫ Set key вешаем на точку или куда хотел.

Sergy: Dima пишет: FUNCTION test() if GetActive()#NIL if valtype(GetActive():varGet())=="N" hb_keyins(".") endif endif return nil Красиво. Осталось разрешить ввод собственно запятой, когда она нужна.

Sergy: Три часа бился, вот что вышло: [pre2] В начале программы ставим SETKEY(44,{||CommaReplace()}) // замена запятой на точку в цифровых полях FUNC CommaReplace() STATIC kb32,kb44 LOCAL key := LastKey() IF (key==44) // запятая ? IF (GetActive() # NIL) .AND. (VALTYPE(GetActive():varGet()) == "N") HB_KeyIns(".") // что и требовалось ELSE kb44 := SETKEY(44,SETKEY(32)) // пустой обработчик пробела подойдет kb32 := SETKEY(32,kb44) // бывш.обработчик 44, т.е. сама функция HB_KeyIns(",") // возвращаем запятую на место ENDIF ELSEIF (key==32) // нажат пробел, нужно восст. обработчик запятой SETKEY(32,kb32) // восст. сохраненного обработчика пробела (по сути, пустой) SETKEY(44,kb44) // восст. обработчика запятой (по сути - вызов этой функции) HB_KeyIns(" ") // возвращаем пробел на место ENDIF RETURN NIL Т.е. все работает так: если юзер нажимает запятую, там, где именно она и нужна - текущий обработчик выключается до тех пор, пока юзер не нажмет пробел. Как только будет нажат пробел (а его чаще всего вводят в текстовых полях), обработчик запятой ставится на место. [/pre2] Все было-бы проще, если-бы удалось запустить Харборовскую функцию SETKEY() с описанным третьим параметром: [pre2]SETKEY(44,{||HB_KeyIns(".")},; {||GetActive() # NIL .AND. VALTYPE(GetActive():varGet())=="N"}) [/pre2] Третий параметр как раз задает условное выполнение кодового блока, переданного вторым параметром. Но у меня он полностью игнроруется, не могу понять почему. Пробовал HB_SETKEY() - тоже самое, ноль эмоций. Поэтому пока так, пока кто-нить не предложит лучший вариант.

Dima: Sergy пишет: SETKEY(44,{||HB_KeyIns(".")},; {||GetActive() # NIL .AND. VALTYPE(GetActive():varGet())=="N"}) а так ? HB_SETKEY(44,{|| if(GetActive() # NIL .AND. VALTYPE(GetActive():varGet())=="N",HB_KeyIns("."),"")})

Sergy: Dima пишет: а так ? HB_SETKEY(44,{|| if(GetActive() # NIL .AND. VALTYPE(GetActive():varGet())=="N",HB_KeyIns("."),"")}) в таком случае мы никогда не увидим запятую - при любом ее нажатии будет отрабатываться блок кода я ведь не зря мучался три часа с примером в пред. сообщении

SergKis: может так: [pre2] HB_SETKEY(44,{|o| o:= GetActive(), if(o # NIL, if(VALTYPE(o:varGet())=="N", HB_KeyIns("."), o:Insert(",")), "")}) где: Text Entry Methods insert() Inserts characters into the editing buffer: insert(<cChar>) --> self Inserts <cChar> into the editing buffer at the current cursor position, shifting the existing contents of the buffer to the right. The cursor is then placed one position to the right of the inserted string. [/pre2]

Sergy: SergKis пишет: может так: ... o:Insert(",") У меня попытка вставки запятой через буфер клавиатуры вызывала очередной вызов обработчика запятой. Что разумеется приводило к зависанию программы. Нужно будет попробовать.

Dima: При нажатии запятой в этом случае в GET вставляется пробел почему то

Sergy: Dima пишет: При нажатии запятой в этом случае в GET вставляется пробел почему то +1

SergKis: Dima пишет: При нажатии запятой в этом случае в GET вставляется пробел почему то пробел не вставляется, вставляется "" и позиция каретки +1, т.е. в tget.prg method insert( cChar ) для ... ::cBuffer := Left( SubStr( ::cBuffer, 1, ::nPos - 1 ) + cChar + SubStr( ::cBuffer, ::nPos ), ::nMaxEdit ) cChar == "" а не "," . что есть печально.

Dima: SergKis пишет: что есть печально. да не все еще отточено в Harbour а метода твоя была супер

SergKis: Dima а так работает: [pre2] hb_SetKey(44, {|| MyTest44(GetActive()) }, {|| GetActive() != NIL}) ... FUNC myTest44( o ) IF o:pos > 1 o:buffer := left(subs(o:buffer, 1, o:pos-1)+','+subs(o:buffer, o:pos+1), len(o:buffer)) ELSE o:buffer := ','+subs(o:buffer, 2) ENDIF o:varPut(o:buffer) o:display() RETURN [/pre2]

Sergy: SergKis пишет: а так работает: теперь курсор не сдвигается с места после установки запятой Но за идею - спасибо. Вот что получилось в итоге (upd @22:00) [pre2] FUNC CommaRepl(oGet) // меняем запятую на точку IF (VALTYPE(oGet:VarGet()) == "C") // текст ? IF (VAL(oGet:VarGet()) # 0) // а по сути цифра ? PutInKbd(".") // меняем на точку ELSE // не цифра, соотв. нужна запятая // тк банальный :Insert(",") пока глючит, извращаемся так: IF oGet:pos > 1 oGet:buffer := LEFT(SUBSTR(oGet:buffer, 1, oGet:pos-1)+','+; SUBSTR(oGet:buffer, oGet:pos+1), LEN(oGet:buffer)) ELSE oGet:buffer := ','+SUBSTR(oGet:buffer, 2) ENDIF oGet:VarPut(oGet:buffer) oGet:Display() oGet:pos += 1 // перемещаем каретку вправо ENDI ELSE // цифра, дата и тп... PutInKbd(".") // меняем на точку ENDIF RETURN [/pre2]

SergKis: Sergy пишет:теперь курсор не сдвигается с места после установки запятой так я делал замену, не вставку, а для упр. позицией каретки служит oGet:pos += 1 или как надо

Sergy: SergKis пишет: так я делал замену, не вставку, а для упр. позицией каретки служит oGet:pos += 1 или как надо Спасибо просто "мой кунг-фу недостаточно хорош" (с) - не силен я в классах.

Sergy: Вопрос. Вот есть такой код: USE (dx+"mail") INDEX (dx+"mail"),(dx+"mail2") NEW // <<< строка 81 IF NETERR() CLOSE mail SELECT(area) RETURN {area,FALSE,FALSE} ENDIF Возникает ошибка: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Вызов из ORDLISTADD(0) Вызов из DBSETINDEX(0) Вызов из OPENMAIL(81) ... Судя по ошибке, dbf открылся, а ntx - нет. Переменная dx совершенно точно к этому моменту определена и существует. Подобный код в Clipper всегда работал и не вызывал ни единой проблемы. Что тут может быть в данном случае ? Как в Harbour однозначно определять успех/неуспех открытия индексов ?

Pasha: Sergy пишет: Судя по ошибке, dbf открылся, а ntx - нет. Наоборот, не открылся dbf, и попытка при этом открыть индекс Причину ищите. Или dbf файл не найден, или что-то связанное с монопольным доступом к нему

Sergy: Pasha пишет: Наоборот, не открылся dbf Вот еще поймал, на другой машине: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Вызов из ORDLISTADD(0) Вызов из DBSETINDEX(0) Вызов из IP_LOAD(734) ... USE (local_dir+IPRICEV) INDEX (local_dir+IPRICEV) EXCLUSIVE NEW // строка 734 local_dir точно существует, ipricev.dbf открылся: Open Tables: 1. BUYPRICE 2. PRICE 3. RESERV 4. AMOUNT 5. AMIMAGE 6. IPRICEV что-то связанное с монопольным доступом к нему В первом примере 100% shared доступ (база с сообщениями - постоянна изменяющаяся, в общем доступе на сервере). Во втором - локальная, справочник, монопольный.

PSP: IPRICEV - это переменная?

Andrey: Sergy пишет: USE (dx+"mail") INDEX (dx+"mail"),(dx+"mail2") NEW // <<< строка 81 Сделай все поочередно: // Блок обработки ошибки bOldError := ERRORBLOCK( {|e| OpenDBF(e, bOldError)} ) BEGIN SEQUENCE USE (dx+"mail") ALIAS MAIL NEW SHARED RECOVER MSG( "Не могу открыть БД " + dx+"mail" + " !" RETURN( .F. ) END SEQUENCE BEGIN SEQUENCE ORDLISTADD( dx+"mail" ) ORDLISTADD( dx+"mail2" ) RECOVER MSG( " Индекс " + dx+"mail не найден ! RETURN( .F. ) END SEQUENCE

Sergy: PSP пишет: IPRICEV - это переменная? вот тут: USE (local_dir+IPRICEV) INDEX (local_dir+IPRICEV) EXCLUSIVE NEW текстовая переменная в списке OpenTables - алиас открытой области/ Его формирует автоматом обработчик ошибок перед завершением программы.

Sergy: Andrey пишет: Сделай все поочередно: во всей программе ? Дело в том, что определенной логики в возникновении данного явления никак найти не могу. Тот-же пример с mail вообще вызывается на каждой машине сети каждые 2-3 минуты (для проверки наличия новых писем) - все работает, хоть бы хны... Вопрос в другом - почему не отрабатывает NETERR() ???

Andrey: Sergy пишет: во всей программе ? Нет. Где вылетает ! Так проще будет тебе понять.

Sergy: Блин, нафига тогда нужен NETERR() ?

petr707: USE (local_dir+IPRICEV) ... EXCLUSIVE NEW 1) перед USE - можно проверить на возможность EXCLUSIVE if enable_excl(local_dir+IPRICEV)// функцию легко создать use endif А еще лучше - переопределить команду USE под свою задачу , примеров много есть 2) Явное указание ALIAS xxx - лучше неявного 3) После USE - также проверить - состоялся ли USE .. alias xxxx if select(xxx)>0 endif 4)NETERR() - ловит не все проблемы открытия таблицы

Sergy: petr707 пишет: А еще лучше - переопределить команду USE под свою задачу , примеров много есть Можно тут по-подробнее плиз ?

PSP: Sergy , попробуй задать alias отличный от имени переменной IPRICEV. К примеру, IPV Что будет?

petr707: Смотрим \include\std.ch и переделываем функцию в описании команды на свою, подключаем к проекту свой redefine.ch если добавите в самом переопределении к обслуживанию USE служебные нагрузки( Public масссивы, переменные, статусы таблиц и прочее) то же нужно сделать и с командами CLOSE и т.д. ниже - только иллюстрация возможности - замена функции DBUSEAREA на NETUSE Внутри NETUSE конечно также есть DbUSEAREA, только еще дополнительная сервисная обертка для обработки ошибок,разнесения блокировок, логирования и прочее.. Этот вариант - когда нет задачи менять PRG-код и можно достичь цели переопределением команд включением еще одного include redefine.ch Обертка может быть и в PRG-коде, но тогда - нужно переписывать все вызовы в PRG-коде. =====\include\std.ch========= #command USE <(db)> [VIA <rdd>] [ALIAS <a>] [<nw: NEW>] ; [<ex: EXCLUSIVE>] [<sh: SHARED>] [<ro: READONLY>] ; [CODEPAGE <cp>] [INDEX <(index1)> [, <(indexN)>]] => ; dbUseArea( <.nw.>, <rdd>, <(db)>, <(a)>, ; if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.> [, <cp>] ) ; [; dbSetIndex( <(index1)> )] ; [; dbSetIndex( <(indexN)> )] ========== redefine.ch============= #command USE <(db)> ; [VIA <rdd>] ; [ALIAS <a>] ; [<new: NEW>] ; [<ex: EXCLUSIVE>] ; [<sh: SHARED>] ; [<ro: READONLY>] ; ; =>if !netuse ( ; <(db)>, <(a)>,if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), ; <.new.>,<.ro.> ; ,5,1," Неудачная попытка открытия таблицы. Повторить? " ; ); ; quit ;; endif

Pasha: Вопрос же простой, как 5 копеек. Все описано в ng по клипперу. Sergy пишет: Блин, нафига тогда нужен NETERR() ? Используется в 2-х случаях. Для append пропустим, это не наш случай. Для use не генерируется исключение, когда файл не открыт по причине того, что он либо уже открыт монопольно другим процессом, либо при попытке открыть его монопольно, когда он уже открыт другим процессом в режиме разделения. Вместо этого устанавливается значение для neterr() Команда use ... index ... Это не одна команда, а две или более: открытие файла, и затем открытие одного или более индексов для уже открытого файла. Причем успешность открытия индекса зависит от успешности выполнения use. Такую команду можно использовать, если есть гарантированная уверенность в успешности открытия файла. Если такой уверенности нет, то надо использовать проверку neterr. Прямо как в примере из ng: USE Customer SHARED NEW IF !NETERR() SET INDEX TO CustNum, CustOrders, CustZip ELSE ? "Файл уже используется другим пользователем" ENDIF Мораль сей басни такова: если файл может открываться разными процессами, то открывать его надо всегда только в режиме shared. и уж никак не exclusive.

Dima: Pasha пишет: Мораль сей басни такова: если файл может открываться разными процессами, то открывать его надо всегда только в режиме shared. и уж никак не exclusive. +1

Sergy: Pasha пишет: Мораль сей басни такова: если файл может открываться разными процессами, то открывать его надо всегда только в режиме shared. и уж никак не exclusive. Вы меня совсем уж за придурка не держите плиз. больше 15 лет разработки и поддержания именно этой задачи. В сети сидят одновременно 20-30 юзеров, которые работали на Clipper задаче. Но медленно. В EXCLUSIVE открывается локальный файл со справочником, который редко меняется (имена, цены, контрагенты). Целиком берется и целиком сливается с сервера в локальную папку. Дальше строится локальный индекс и открывается в ESXCLUSIVE. Первый пример (с mail.dbf) - способ открытия по умолчанию, т.е. SHARED (тк в самом начале программы установка SET EXCLUSIVE OFF). Второй - аналогичная ситуация, но файл - локальный и открывается монопольно. И не может быть открыт никаким другим процессом. Это временная таблица, которая будет стерта при выходе. Поэтому вопрос пока открыт: почему с переходом на Harbour стали возникать ошибки такого рода: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD

Sergy: PSP пишет: попробуй задать alias отличный от имени переменной IPRICEV. К примеру, IPV Что будет? сделал по другому - убрал нахрен переменную IPRICEV и тупо вписал: USE (local_dir+"ipricev") INDEX (local_dir+"ipricev") EXCLUSIVE NEW посмотрим, что будет. Пока с вероятностью 50/50 возникает ошибка. :(

Dima: Sergy пишет: USE (local_dir+IPRICEV) INDEX (local_dir+IPRICEV) EXCLUSIVE NEW Попробуй жестко указывать ALIAS , что то было у меня похожее ЗЫ USE (local_dir+IPRICEV) INDEX (local_dir+IPRICEV) ALIAS TEMPBASE EXCLUSIVE NEW

Sergy: http://www.hmgforum.com/viewtopic.php?f=5&t=2169 Походу существует какая-то фигня, из-за которой Harbour не ждет и не пытается повторить несколько раз (как Clipper ?) попытку открыть таблицу и индекс... Т.е. попытался один раз - сразу ставим юзера в известность... каким только вот образом ?

Pasha: Sergy пишет: Возникает ошибка: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Вызов из ORDLISTADD(0) Вызов из DBSETINDEX(0) Вызов из OPENMAIL(81) ... Судя по ошибке, dbf открылся, а ntx - нет. Поясняю второй раз. Ошибка возникла при открытии индекса, вызов из dbSetIndex/OrdListAdd. Код ошибки 2001 - это EDBCMD_NOTABLE, т.е вызов из неоткрытой рабочей области. Это означает, что предыдущая команда use была неудачной. Чтобы было понятнее, вот исходник OrdListAdd из сырцов харбора: HB_FUNC( ORDLISTADD ) { AREAP pArea = ( AREAP ) hb_rddGetCurrentWorkAreaPointer(); // текущая рабочая область if( pArea ) // Проверка, открыта ли рабочая область { // Открытие индекса ... } else // не открыта, возникает ошибка 2001, здесь и только здесь hb_errRT_DBCMD( EG_NOTABLE, EDBCMD_NOTABLE, NULL, HB_ERR_FUNCNAME ); } Вы меня совсем уж за придурка не держите плиз. больше 15 лет разработки и поддержания именно этой задачи. В сети сидят одновременно 20-30 юзеров работали на Clipper задаче. Но медленно. В EXCLUSIVE открывается локальный файл со справочником, который редко меняется (имена, цены, контрагенты). Целиком берется и целиком сливается. Дальше строится локальный индекс и открывается в ESXCLUSIVE. Первый пример (с mail.dbf) - способ открытия по умолчанию, т.е. SHARED (тк в самом начале программы установка SET EXCLUSIVE OFF). Второй - аналогичная ситуация, но файл - локальный и открывается монопольно. И не может быть открыт никаким другим процессом. Это временная таблица, которая будет стерта при выходе. Поэтому вопрос пока открыт: почему с переходом на Harbour стали возникать ошибки такого рода: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Что мешает вам вставить проверку на neterr после выполнения use ? Сразу все станет на свои места. По вашему коду не видно, в каком режиме открывается mail.dbf. Если не устанавливалось никакого нестандартного обработчика ошибок, то что клиппер, что харбор не будет генерировать исключение только в том случае, когда файл не открыт из-за ошибки доступа к нему. Насчет второго примера, когда открывается локальный файл в режиме exclusive. Возможно, на этом компьютере была запущена вторая копия программы, которая попытается открыть этот файл также монопольно, и возникнет та же ошибка. Я же ваш код не вижу, могу только сказать по логу ошибки, по какой причине она возникла. Третий раз повторять надо или ограничимся ? В теме по ссылке на hmgforum ясно видно, что файл открывается монопольно. И что непонятно ? Что хотели, то и получили. Файл уже открыт другой задачей, и не может быть открыт монопольно. А что это за фантазии насчет того, что клиппер пытается несколько раз открывать файл ?

petr707: Цитата: И не может быть открыт никаким другим процессом Этого (знать наверняка и) утверждать никак невозможно. Есть , например, Google Desktop, который при своей работе может занимать монопольно файлы DBF, NTX и прочие и легко может завалить задачу. Да и зависшие блокировки от операционки бывают да мало ли чего. В терминальном режиме можно потерять сеанс задачи, который будет жить на таблицах самостоятельно.

Sergy: Pasha пишет: Что мешает вам вставить проверку на neterr после выполнения use ? Вот лог ошибки: Ошибка DBCMD/2001 Файл не открыт: ORDLISTADD Вызов из ORDLISTADD(0) Вызов из DBSETINDEX(0) Вызов из IP_LOAD(734) Вызов из PRINTPRLIST(3715) ... Open Tables: 1. BUYPRICE 2. PRICE 3. RESERV 4. AMOUNT 5. AMIMAGE 6. IPRICEV Вот код, который работает в данном случае: [pre2] area:=SELECT() IF !FileExist(local_dir+"ipricev.dbf") // нет образа локально - загружаем CheckNLoad("ipricev") // копируем с сервера в локальную папку и строим индекс CLOSE ipricev ENDI USE (local_dir+"ipricev") INDEX (local_dir+"ipricev") EXCLUSIVE NEW /// <<< строка 734 IF NETERR() /// сюда уже не попадает, программа завершила работу [/pre2] Получается, что в рабочей области N6 уже открыт dbf, но не открыт индекс... // не открыта, возникает ошибка 2001, здесь и только здесь Мда... нужно будет всерьез задуматься... Тогда каковы причины не открытия *.dbf ? Ведь он окрывается в 9 случаях из 10 нормально. И юзеры рядом работают...

Sergy: Pasha пишет: Возможно, на этом компьютере была запущена вторая копия программы, Это тоже полностью исключено. Открывается в монопольном режиме mem файл с сохраненными переменными. Вторая копия за 15 лет ни разу еще не смогла начать работать в таком режиме. Выдается сообщение пользователю и привет. А что это за фантазии насчет того, что клиппер пытается несколько раз открывать файл ? Х.е. знает - посмотрел по тому примеру, дядька советует вьетнамцу попытаться несколько сек. подождать. Clipper ведь ни разу на этом месте не спотыкался. Вот и подумал...

Dima: Sergy пишет: USE (local_dir+"ipricev") INDEX (local_dir+"ipricev") EXCLUSIVE NEW После того как поюзал эту базу локально , ты ее закрываешь ?

Pasha: В этом фрагменте кода ошибки нет. Но неизвестно, что в остальном коде. Возможно, файл ipricev уже был открыт в момент выдачи команды use в строке 734 Сделайте тест: use ipricev EXCLUSIVE NEW ? Alias(), NetErr() use ipricev EXCLUSIVE NEW ? Alias(), NetErr() Результат будет ожидаем: IPRICEV .T. .F. Если к команде use добавить еще опцию index, то как раз получим желаемый результат: попытка открытия индекса в неоткрытой р.о, и ошибка 2001

Sergy: Dima пишет: После того как поюзал эту базу локально , ты ее закрываешь ? Разумеется. На выходе из каждой процедуры формирования отчета идет CloseAll(), по сути обертка для CLOSE ALL и нескольких внутренних обработок.

Sergy: Pasha пишет: В этом фрагменте кода ошибки нет. Но неизвестно, что в остальном коде. Возможно, файл ipricev уже был открыт в момент выдачи команды use в строке 734 Сделайте тест: use ipricev EXCLUSIVE NEW ? Alias(), NetErr() use ipricev EXCLUSIVE NEW ? Alias(), NetErr() Результат будет ожидаем: IPRICEV .T. .F. Если к команде use добавить еще опцию index, то как раз получим желаемый результат: попытка открытия индекса в неоткрытой р.о, и ошибка 2001 Проблема в том, что на компе с Harbour (где база локальна) я вообще ни разу не смог получить подобные ошибки. Они возникают только в сети после перехода на Harbour. И то через раз - то есть, то нет...

Pasha: Sergy пишет: Тогда каковы причины не открытия *.dbf ? Ведь он окрывается в 9 случаях из 10 нормально. И юзеры рядом работают... Наиболее вероятную причину я назвал. Из текста errorsys видно: // Set NetErr() of there was a database open error IF oError:genCode == EG_OPEN .AND. ; oError:osCode == 32 .AND. ; oError:canDefault NetErr( .T. ) RETURN .F. ENDIF что NetErr( .T. ) устанавливается при ошибке открытия по команде use, когда oError:osCode == 32 32 - это Sharing violation Что такое Sharing violation думаю обьяснять не надо

SergKis: Sergy Еще с Clipper делаю примерно так: [pre2] bOldError := ErrorBlock( { |e|break( e ) } ) BEGIN SEQUENCE dbUseArea( .F., cRdd, cDbf, cAls, lSha ) IF ! Used() DO WHILE s-- >= 0 dbUseArea( .F., cRdd, cDbf, cAls, lSha ) IF Used(); EXIT ENDIF hb_IdleSleep(0.1) ENDDO ENDIF RECOVER USING oError lRet := .F. END SEQUENCE ErrorBlock( bOldError ) [/pre2] практика использования clipper, hb показала, даже на локальной базе, при больших расчетах, простое use не открывает файл handle нет - на это может влиять антивирус (особенно Касперский - это наш опыт). use в цикле - решение проблеммы

PSP: Да, кстати, антивирус - реальная причина.

Dima: SergKis пишет: особенно Касперский - это наш опыт а у меня (вернее у моего клиента) тоже делал NOD32 , сканировал и лочил DBF базы

Pasha: В конце концов, поведение совеременных ОС при открытии файла в ntvdm b в реальном режиме действительно может быть различным. Я встречался с случаями, когда серверные ОС ведут себя неадекватно: файл вроде бы уже создан, а открыть его нельзя. Могут гадить и аетивирусы. И харбор тут ни при чем, и средствами харбора этот вопрос не решить. А решить его можно простыми приемами: Если используется локально временный файл, то создавать его именно как временный, и тогда его можно открывать монопольно. Во всех остальных случаях открывать файл как shared, особенно если он располагается на сетевых ресурсах Ну и вместо последовательности: use ... index ... new использовать use ... if ! neterr() set index to ...

SergKis: Pasha +1 то что use м set index надо разделить во времени - однозначно

Sergy: Pasha пишет: Если используется локально временный файл, то создавать его именно как временный, и тогда его можно открывать монопольно Именно так и сделано. Локальные - монопольно, удаленные - shared. В остальном - мысли разумные и дали пищу для размышлений, спасибо. Поковырялся у себя в errorsys.ch, вот что обнаружил: [pre2] IF (e:genCode == EG_ZERODIV) // По умолчанию деление на ноль дает ноль RETURN (0) ENDI IF (e:SubSystem == 'DBFNTX') .AND. ; // специфика dbfntx & Win2K based servers (e:SubCode == 1035) .AND. ; (e:tries < 25) RETURN (.T.) ENDI IF (e:genCode == EG_LOCK) .AND. e:canDefault // обработка специфич.ошибки ntx в 5.2e RETURN (.F.) ENDI IF (e:genCode == EG_OPEN) .AND. (e:osCode == 32) .AND. e:canDefault // Для ошибки открытия файла в сетевом окружении..установка NETERR() // и значения SUBSYSTEM по умолчанию NetErr(.T.) RETURN (.F.) // NOTE ENDI IF (e:genCode == EG_APPENDLOCK) .AND. e:canDefault // Для ошибки блокировки во время APPEND BLANK..установка NETERR() // и значения SUBSYSTEM по умолчанию NetErr(.T.) RETURN (.F.) // NOTE END [/pre2] Откуда это могло у меня взяться - ума не приложу. То-ли это что-то из базовой поставки Clipper еще с 5.01, то-ли где-то нарыл, возможно с этого форума. У меня просто дописано сохранение сообщений, стека вызовов, открытых алиасов в report.log с последуюущим скидыванием его на сервер, чтобы можно было понять, что происходит у клиентов. Поэтому этот файл еще жив. Вопрос: что из этого лишнее и чего (возможно) не хватает ? там есть некий e:tries - может быть использовать его ?

Andrey: Sergy пишет: Вопрос: что из этого лишнее и чего (возможно) не хватает ? Выкинуть его нафиг и взять из поставки Харбора. Я писал вам, да и все тоже это скажут: Харбор более требователен к синтаксису ! Что есть очень хорошо. Харбор не отвечает за старые ошибки Клипера, он более СТАБИЛЬНЕЙ по работе в сети и локально. НЕ ТАЩИТЕ весь функционал который был на клипере, переделывайте узкие места: открытие/закрытие/блокировки баз !!! Я тоже сначала натыкался на это и злился... После переделок, со временем все становиться прозрачно и понятно !

Pasha: Sergy пишет: IF (e:SubSystem == 'DBFNTX') .AND. ; // специфика dbfntx & Win2K based servers (e:SubCode == 1035) .AND. ; (e:tries < 25) RETURN (.T.) ENDI могу только сказать, что 1035 - это LOCKTIMEOUT

Sergy: Сделал вот так: [pre2] #command USE <(db)> ; [VIA <rdd>] ; [ALIAS <a>] ; [<new: NEW>] ; [<ex: EXCLUSIVE>] ; [<sh: SHARED>] ; [<ro: READONLY>] ; [INDEX <(index1)> [, <(indexn)>]] ; ; => NetUse( ; <.new.>, <rdd>, <(db)>, <(a)>, ; if(<.sh.> .or. <.ex.>, !<.ex.>, NIL), <.ro.> ; ) ; ; [; IIF(USED(),NetSetIndex( <(index1)> ),NIL)] ; [; IIF(USED(),NetSetIndex( <(indexn)> ),NIL)] // далее: * ----------------------------------------------- * FUNC NetUse(lNew,cRdd,cDb,cAlias,lShared,lReadonly) LOCAL start_time,res,cnt cnt := 0 start_time := SECONDS() REPEAT DBUSEAREA(lNew,cRdd,cDb,cAlias,lShared,lReadonly) res:=USED() IF res EXIT ENDIF cnt++ hb_IdleSleep(0.1) UNTIL (ABS(SECONDS() - start_time) > 1) // не более 1 сек с уч.полуночи IF (cnt > 0) OutReportLog("NetUse("+cDb+") tried to open "+NTRIM(cnt)+" times and "+IIF(res,"OK","FAIL")) ENDIF RETURN res * ------------------- * FUNC NetSetIndex(cName) LOCAL start_time,res,cnt cnt := 0 start_time := SECONDS() REPEAT res:=DBSETINDEX(cName) IF res; EXIT; ENDIF hb_IdleSleep(0.1) cnt++ UNTIL (ABS(SECONDS()-start_time) > 1) // не более 1 сек c уч.перехода полуночи IF (cnt > 0) OutReportLog("NetSetIndex("+cName+") tried to open "+NTRIM(cnt)+" times and "+IIF(res,"OK","FAIL")) ENDIF RETURN res [/pre2] Получил одно вот такое сообщение: 27.08.2013 09:45:46 NetUse(caroute) tried to open 1 times and OK и несколько вот таких: Ошибка DBFNTX/1201 Файл не индексирован Вызов из DBSEEK(0) Вызов из GETNOMINALPRICE(322) Вызов из LOADDATA(148) ... Ошибка DBFNTX/1201 Файл не индексирован Вызов из DBSEEK(0) Вызов из DBVIEW(4752) Вызов из CARMANAGER(515) ... Совершенно точно вчера/позавчера и под Clipper этот код работал. В NetSetIndex() поставил проверку успешности открытия индекса ( res:=DBSETINDEX() ), но почему-то она не сработала ?

Vlad04: Из моего опыта перехода с Clipper на Харбор (это было уже давно- несколько лет назад). Пришлось в местах сохранения данных дописать везде Commit. Clipper и так нормально сохранял .А Харбор без этой команды, по- видимому используя буфер Windows, сбрасывал мусор в базы.

Vlad04: От DBFNTX отказался, сразу переделывал под cdx

Dima: Sergy я что то пропустил а антивирус стоит ? в исключениях числятся у него папки с базами и прогой ?

Sergy: Нашел в коде еще несколько прямых вызовов DBUSEAREA() и DBSETNDEX() - заменил их на свои NetUse() и NetSetIndex(). Пока конечно рано говорить, но ситуация по ходу стабилизировалась - нет непонятных сообщений о неоткрытых областях, отсутствии индексации и тп... Одна машина пока прислала несколько отчетов о том, что с первого раза не удалось открыть таблицу.

Sergy: Dima пишет: я что то пропустил а антивирус стоит ? в исключениях числятся у него папки с базами и прогой ? Стоит официальный лицензионный NOD32 - на сервере серверная версия, у клиентов - клиентские. Разумеется на сервере *.dbf и *.ntx стоят в исключениях. Программу в исключения не ставил никогда - проблем особых не было. Ну проверит один раз при запуске - делов-то... Все-таки EXE - он может быть заражен при определенном стечении обстоятельств... На рабочих машинах - 100% гарантии нет, но админ сети вроде в курсе. Кстати будет повод проверить...

SergKis: Sergy пишет:res:=DBSETINDEX(cName) IF res; EXIT; ENDIF Clipper ng говорит dbSetIndex() return NIL, в hb dbSetIndex() это вызов hb_func( ORDLISTADD ) и там возвраты разные и написано: /* Clipper clears NETERR flag when index is open */ hb_rddSetNetErr( HB_FALSE ); может лучше из SET INDEX ... функции в команде использовать, ? OrdCount() даст кол-во подключенных index\tag

Pasha: Sergy пишет: Получил одно вот такое сообщение: 27.08.2013 09:45:46 NetUse(caroute) tried to open 1 times and OK Это говорит о том, что менее чем на секунду файл все-таки был открыт каким-то процессом. А вот каким - в этом мы вряд ли поможем. Возможные предположения уже высказаны. Хорошо бы еще в лог писать режим открытия - lShared и несколько вот таких: Ошибка DBFNTX/1201 Файл не индексирован В NetSetIndex() поставил проверку успешности открытия индекса ( res:=DBSETINDEX() ), но почему-то она не сработала ? Если dbSetIndex вернул .t. - значит, индекс был открыт успешно, и никак не иначе. А причина ошибки 1201 может быть другой: индекс был закрыт, был вызов set order to 0, или set order на несуществующий индекс, или где-то ошибка в имени индекса, в результате чего текущий индекс оказался не установлен. Сергей, только не говорите, что такого не может быть, иначе мы ничем не сможем помочь. Пересмотрите еще раз свой код, вставьте дополнительные логи в конце концов.

Pasha: SergKis пишет: Clipper ng говорит dbSetIndex() return NIL, в hb dbSetIndex() это вызов hb_func( ORDLISTADD ) и там возвраты разные и написано: /* Clipper clears NETERR flag when index is open */ hb_rddSetNetErr( HB_FALSE ); может лучше из SET INDEX ... функции в команде использовать, ? OrdCount() даст кол-во подключенных index\tag Да, правильно, успешность открытия индекса лучше проверять чем нибудь вроде: IndexOrd() # 0 ! Empty(IndexKey()) ! Empty(ordName())

Dima: Sergy Где то есть аналогичная тема от AndreyZh тоже переходил человек с Clipper и тоже были не увязки и споры. Сегодня у него кажется все нормально так что даже редко тут появляется ;) PS А лагов в сети нет ?

Sergy: Pasha пишет: Сергей, только не говорите, что такого не может быть Хорошо, не буду. Dima пишет: А лагов в сети нет ? Что имеется в виду и как это выяснить ?

Dima: Sergy На "проблемных" станциях как вариант дай команду ping ipсервера -n 100 -l 1400 и посмотри результат

PSP: Сеть лучше утилитой iperf проверить в режиме трансляции udp-пакетов.

Sergy: SergKis пишет: Clipper ng говорит dbSetIndex() return NIL, в hb dbSetIndex() это вызов hb_func( ORDLISTADD ) и там возвраты разные и написано: /* Clipper clears NETERR flag when index is open */ hb_rddSetNetErr( HB_FALSE ); может лучше из SET INDEX ... функции в команде использовать, ? OrdCount() даст кол-во подключенных index\tag Почитал Changelog.txt: * changed ordListAdd()/dbSetIndex() - now they return logical value with information about success Пока остановился на этом варианте. Несколько предыдущих ошибок "Файл не индексирован" выскочили из-за того, что в паре-тройке мест остались прямые вызовы DBUSEAREA/DBSETINDEX вместо замененных мною USE ... INDEX ... upd: Поймал наконец-то и такие ошибки: 27.08.2013 14:37:33 NetSetIndex(system) tried to open 1 times and OK 27.08.2013 14:47:22 NetSetIndex(F:\WORK\DATA\carjob2.ntx) tried to open 1 times and OK Что самое странное - программа запускается на сервере и управляется через RDP - т.е. диск с базой у нее вообще локальный, а не по сети. И проверил, что Харборовский DBSETINDEX() возвращает корректный результат для обработки в NetSetIndex() ... продолжаю наблюдения. Спасибо коллективному разуму.

SergKis: Sergy пишет:Почитал Changelog.txt первоисточник SRC hb 3.2 [pre2] HB_FUNC( ORDLISTADD ) { ... if( ! HB_ISNIL( 1 ) ) hb_errRT_DBCMD( EG_ARG, EDBCMD_ORDLSTADD_BADPARAMETER, NULL, HB_ERR_FUNCNAME ); return; !!!!!!!!!! } ... if( ! pOrderInfo.itmResult || HB_IS_NIL( pOrderInfo.itmResult ) ) hb_retl( errCode == HB_SUCCESS ); !!!! ... FUNCTION dbSetIndex( cIndexName ) RETURN ordListAdd( cIndexName ) [/pre2] Sergy пишет:Что самое странное - программа запускается на сервере и управляется через RDP - т.е. диск с базой у нее вообще локальный, а не по сети SergKis пишет: использования clipper, hb показала, даже на локальной базе ... причем полгода может работать, а потом кердык - начнет елозить. Разбор полетов покажет как правило анти\вирус обновили, заменили ...

Sergy: Мужчины, огромная вам всем благодарность за помощь и поддержку! Третий день программа работает практически как часы на ежедневной нагрузке. И как работает - летает, как ласточка, все юзеры довольны. Ничего того, что-бы меня удивило в ее поведении - нет. А ведь неделей раньше рвал волосы во всех местах и уже подумывал - бросить все нак*й и вернуться на Clipper. Кое-где выплывают косяки моего программирования, которых не замечал наш старый добрый 5.2e. Потихоньку накапливаются сообщения о том, что таблица/индекс не открылись с первого раза. Пытаюсь понять логику - информации мало, но похоже, что они возникают на "сверхбыстрых" машинах на локальных ресурсах. Например, "разгруженном" от юзеров терминальном сервере (рано утром или поздно вечером). Благодаря Вашим наработкам в этой ветке, научил программу "пипикать" wave-файлами из ресурсов, блокировать крестик, менять заголовок Windows-окошка. Так классно! Спасибо еще раз! На этом не прощаюсь - искренне надеюсь, еще будут интересные вопросы и обсуждения.

Pasha: Запускаю свою харбор-программу, которая открывает файлы через dbfcdx - shared. Запускаю dosbox, а в нем - программу, которая открывает dbf-файл монопольно (свой старый dbview под ms dos). Файл не должен открываться, но он открывается. Если попытаться открыть этот файл монопольно win32-программой, то попытка будет неуспешной, как и должно быть. Выходит, что открытие файлов под ntvdm/dosbox происходит не по правилам. Вот поэтому старая клиппер-программа и всегда открывала файлы, которые не должна была открывать, в отличие от харбор-программы, которая ведет себя, как ей и положено.

Dima: Pasha пишет: Запускаю свою харбор-программу, которая открывает файлы через dbfcdx - shared. Запускаю dosbox, а в нем - программу, которая открывает dbf-файл монопольно (свой старый dbview под ms dos). Файл не должен открываться, но он открывается. Попробовал повторить (без DOSBOX разумеется). Файл не открылся. Первой запустил Harbour прогу [pre2] proc main use test shared new browse() return [/pre2] Вторая на Clipper [pre2] use test exclusive new browse() // бровса я не увидел и прога сразу завершила свою работу [/pre2] ЗЫ неисповедимы пути господни NTVDM

Sergy: Возникло подозрение, что сохранение длинной CHAR переменной в поле таблицы "портит" символы "нижней" части ASCII с кодом, меньшим CHR(32). Чтобы проверить это, хочу попробовать USE (cTable) CODEPAGE (...) Подскажите плиз, какую страницу нужно указать, чтобы полностью отказаться от перекодировки ? Нужен какой-нить "NULL" или "WESTERN EUROPE". Какие они вообще бывают, кроме "RU866" и "RU1251" - попробую методом перебора...

nick_mi: HB_FUNC_EXTERN( HB_CODEPAGE_BG866 ); HB_FUNC_EXTERN( HB_CODEPAGE_BGISO ); HB_FUNC_EXTERN( HB_CODEPAGE_BGMIK ); HB_FUNC_EXTERN( HB_CODEPAGE_BGWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_CS852 ); HB_FUNC_EXTERN( HB_CODEPAGE_CS852C ); HB_FUNC_EXTERN( HB_CODEPAGE_CSISO ); HB_FUNC_EXTERN( HB_CODEPAGE_CSKAMC ); HB_FUNC_EXTERN( HB_CODEPAGE_CSWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_DE850 ); HB_FUNC_EXTERN( HB_CODEPAGE_DE850M ); HB_FUNC_EXTERN( HB_CODEPAGE_DEISO ); HB_FUNC_EXTERN( HB_CODEPAGE_DEWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_DK865 ); HB_FUNC_EXTERN( HB_CODEPAGE_EL437 ); HB_FUNC_EXTERN( HB_CODEPAGE_EL737 ); HB_FUNC_EXTERN( HB_CODEPAGE_ELISO ); HB_FUNC_EXTERN( HB_CODEPAGE_ELWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_EN ); HB_FUNC_EXTERN( HB_CODEPAGE_ES850 ); HB_FUNC_EXTERN( HB_CODEPAGE_ES850C ); HB_FUNC_EXTERN( HB_CODEPAGE_ES850M ); HB_FUNC_EXTERN( HB_CODEPAGE_ESISO ); HB_FUNC_EXTERN( HB_CODEPAGE_ESMWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_ESWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_FI850 ); HB_FUNC_EXTERN( HB_CODEPAGE_FR850 ); HB_FUNC_EXTERN( HB_CODEPAGE_FR850M ); HB_FUNC_EXTERN( HB_CODEPAGE_FRISO ); HB_FUNC_EXTERN( HB_CODEPAGE_FRWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_HR646 ); HB_FUNC_EXTERN( HB_CODEPAGE_HR852 ); HB_FUNC_EXTERN( HB_CODEPAGE_HRISO ); HB_FUNC_EXTERN( HB_CODEPAGE_HRWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_HU852 ); HB_FUNC_EXTERN( HB_CODEPAGE_HU852C ); HB_FUNC_EXTERN( HB_CODEPAGE_HUISO ); HB_FUNC_EXTERN( HB_CODEPAGE_HUWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_IS850 ); HB_FUNC_EXTERN( HB_CODEPAGE_IS861 ); HB_FUNC_EXTERN( HB_CODEPAGE_IT437 ); HB_FUNC_EXTERN( HB_CODEPAGE_IT850 ); HB_FUNC_EXTERN( HB_CODEPAGE_IT850M ); HB_FUNC_EXTERN( HB_CODEPAGE_ITISB ); HB_FUNC_EXTERN( HB_CODEPAGE_ITISO ); HB_FUNC_EXTERN( HB_CODEPAGE_ITWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_LT775 ); HB_FUNC_EXTERN( HB_CODEPAGE_LTWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_NL850 ); HB_FUNC_EXTERN( HB_CODEPAGE_NL850M ); HB_FUNC_EXTERN( HB_CODEPAGE_NO865 ); HB_FUNC_EXTERN( HB_CODEPAGE_PL852 ); HB_FUNC_EXTERN( HB_CODEPAGE_PLISO ); HB_FUNC_EXTERN( HB_CODEPAGE_PLMAZ ); HB_FUNC_EXTERN( HB_CODEPAGE_PLWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_PT850 ); HB_FUNC_EXTERN( HB_CODEPAGE_PT860 ); HB_FUNC_EXTERN( HB_CODEPAGE_PTISO ); HB_FUNC_EXTERN( HB_CODEPAGE_RO852 ); HB_FUNC_EXTERN( HB_CODEPAGE_ROISO ); HB_FUNC_EXTERN( HB_CODEPAGE_ROWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_RU1251 ); HB_FUNC_EXTERN( HB_CODEPAGE_RU866 ); HB_FUNC_EXTERN( HB_CODEPAGE_RUISO ); HB_FUNC_EXTERN( HB_CODEPAGE_RUKOI8 ); HB_FUNC_EXTERN( HB_CODEPAGE_SK852 ); HB_FUNC_EXTERN( HB_CODEPAGE_SK852C ); HB_FUNC_EXTERN( HB_CODEPAGE_SKISO ); HB_FUNC_EXTERN( HB_CODEPAGE_SKKAMC ); HB_FUNC_EXTERN( HB_CODEPAGE_SKWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_SL646 ); HB_FUNC_EXTERN( HB_CODEPAGE_SL852 ); HB_FUNC_EXTERN( HB_CODEPAGE_SLISO ); HB_FUNC_EXTERN( HB_CODEPAGE_SLWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_SR646 ); HB_FUNC_EXTERN( HB_CODEPAGE_SR646C ); HB_FUNC_EXTERN( HB_CODEPAGE_SRWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_SV437C ); HB_FUNC_EXTERN( HB_CODEPAGE_SV850 ); HB_FUNC_EXTERN( HB_CODEPAGE_SV850M ); HB_FUNC_EXTERN( HB_CODEPAGE_SVISO ); HB_FUNC_EXTERN( HB_CODEPAGE_SVWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_TR857 ); HB_FUNC_EXTERN( HB_CODEPAGE_TRISO ); HB_FUNC_EXTERN( HB_CODEPAGE_TRWIN ); HB_FUNC_EXTERN( HB_CODEPAGE_UA1125 ); HB_FUNC_EXTERN( HB_CODEPAGE_UA1251 ); HB_FUNC_EXTERN( HB_CODEPAGE_UA866 ); HB_FUNC_EXTERN( HB_CODEPAGE_UAKOI8 );

Pasha: Sergy пишет: Подскажите плиз, какую страницу нужно указать, чтобы полностью отказаться от перекодировки ? Перекодировка не выполняется, если кодовая страница программы совпадает с кодовой страницей, указанной в команде use. Если в use не указана codepage, то она будет такой же, что в hb_cdpSelect, и перекодировки также не будет.

Sergy: Pasha пишет: Перекодировка не выполняется, если кодовая страница программы совпадает с кодовой страницей, указанной в команде use. Если в use не указана codepage, то она будет такой же, что в hb_cdpSelect, и перекодировки также не будет. А может быть какая-нибудь петрушка с SAVESCREEN / RESTSCREEN ? В одном месте программы, среди кучи однотипных вызовов: сохранение экрана - диалог - восстановление наблюдаю такой глюк: символы CHR(16) заменяются на "?" и соотв. выводятся назад уже не в виде треугольников, а в виде знаков вопроса. Сначала думал на запись в файл (экраны складываются локально, чтобы не тратить память Clipper). Поигрался с CODEPAGE, потом переделал на сохранение в memvar-переменных - тоже самое. Косяк совершенно незначительный, но бесит... Не люблю я эту неопределенность...

Dima: Sergy пишет: символы CHR(16) заменяются на "?" и соотв. выводятся назад уже не в виде треугольников, а в виде знаков вопроса. Простой и понятный исходник сюда. У себя такого не наблюдал. PS GTWVT

Pasha: Sergy пишет: А может быть какая-нибудь петрушка с SAVESCREEN / RESTSCREEN ? Совершенно непонятно, в чем заключается ваша проблема. Разве трудно сделать простейшие тесты, чтобы проверить, как работает кодовая страница в rdd, вроде такого: REQUEST HB_CODEPAGE_RU866 hb_cdpSelect( "RU866" ) dbCreate('aa', {{'CC','C',1,0}},, .t., 'aa',, 'RU866') for i := 0 to 255 aa->(dbAppend()) aa->CC := Chr(i) next и посмотреть на выходной файл ? Да и протестировать savescreen/restscreen ? @ 0,0 say chr(16) cc := SaveScreen(0,0,0,0) RestScreen(0,2,0,2,cc)

petr707: Нет никакой перекодировки и треугольника уже нет Просто в используемом Вами шрифте на этом месте другое изображение. Есть стандартноая утилита Windows TableMap ( Пуск\Все программы\Служебные\Таблица символов) Если треугольник сильно нужен, можно создать свой шрифт.

Sergy: Все эти выкладки конечно здорово, но факт остается фактом... :( По поводу шрифта - тестировал Lucida Console. Эффект повторяется 1:1. 900 вызовов проходят нормально, а один - корявится. Поэтому пока не могу создать тест... Такая вот петрушка.

Pasha: Так огласите наконец-то, что за факт. Все телепаты в отпуске. Сначала вы говорили что-то перекодировку в use, потом про savescreen. Трудно отвечать на незаданный вопрос, а разгадывать шарады не хочется.

Sergy: Pasha пишет: Так огласите наконец-то, что за факт. Все телепаты в отпуске. Сначала вы говорили что-то перекодировку в use, потом про savescreen. Трудно отвечать на незаданный вопрос, а разгадывать шарады не хочется. Есть функция SaveConsole(), которая делает SAVESCREEN и кладет его в локальную DBF таблицу, чтобы не расходовать память. Ровно в одном месте программы в таблицу стали попадать символы "?" вместо CHR(16). И соотв. при восстановлении экрана в RestConsole() происходит RESTSCREEN(0,0,MAXROW(),MAXCOL(), console->buffer) Ровно в одном месте программы. Первая мысль была на USE ... CODEPAGE. Спросил, знающий человек быстро откликнулся (за что ему спасибо), проверил - не помогло. Стал копать дальше. Оказывается, SAVESCREEN именно в этом месте программы возвращает "испорченные" коды. Которые попадают в таблицу и USE уже ни причем - он пишет в таблицу то, что ему вернул SAVESCREEN(). Во всей программе все работает как нужно. В этом, одном, единственном месте, написанном на чистом Clipper безо всяких наворотов - такая вот петрушка... Поэтому, собственно, пока единственный вопрос - были ли у кого-нить на Harbour проблемы с SAVESCREEN() / RESTSCREEN() или нет.

PSP: Я никогда, даже во времена работы с Клиппером, не сохранял экраны в dbf. Просто делал сохранение в массив, выполнявший роль стека LIFO (last in first out). Даже с Клиппером память ни разу не исчерпалась.

Dima: PSP пишет: Я никогда, даже во времена работы с Клиппером, не сохранял экраны в dbf. +1

petr707: символы "?" ( это картинка) вместо CHR(16) ( а это - число,байт,...) Либо - символы "?" вместо символа "x" , либо CHR(n) вместо CHR(16) Сохраняейте в бинарный файл (типа TXT) и смотрите содержимое любым Hex-вьюером(editor)

Sergy: PSP пишет: Я никогда, даже во времена работы с Клиппером, не сохранял экраны в dbf. Просто делал сохранение в массив, выполнявший роль стека LIFO (last in first out). Даже с Клиппером память ни разу не исчерпалась. Выключить эту опцию сегодня - дело трех строчек кода. Наверное так и сделаю. Но это пока не решает этого мелкого вопросика, о котором речь. petr707 пишет: символы "?" ( это картинка) вместо CHR(16) ( а это - число,байт,...) Либо - символы "?" вместо символа "x" , либо CHR(n) вместо CHR(16) Сохраняейте в бинарный файл (типа TXT) и смотрите содержимое любым Hex-вьюером(editor) Символ CHR(16) - это такой треугольник, который изображает, что данный пункт имеет вложенное подменю. Например: "Документы >" при выборе этого пункта вызывается меню с документами. После SAVESCREEN/RESTSCREEN получается так: "Документы ?" т.е. вместо CHR(16) получается CHR(63) - как раз выяснилось из сравнения слитых в txt результатов SAVESCREEN() Надеюсь, что понятно объяснил.

PSP: А какой тип поля в dbf?

Pasha: Символ CHR(16) - это такой треугольник, который изображает, что данный пункт имеет вложенное подменю. Например: "Документы >" при выборе этого пункта вызывается меню с документами. Я точно также отмечаю меню с подменю символом Chr(16), и тоже использую при этом savescreen/restscreen. Правда, сохраняю все в структурах типа стек. Проблем не возникало.

Sergy: PSP пишет: А какой тип поля в dbf? CHAR, с размером ширина*высота экрана * 2 (для атрибутов) Pasha пишет: Я точно также отмечаю меню с подменю символом Chr(16), и тоже использую при этом savescreen/restscreen. Правда, сохраняю все в структурах типа стек. Проблем не возникало. Сейчас стало совершенно понятно, что структуры точно не причем. RESTSCREEN() возвращает вместо треугольника знак вопроса.

AlexMyr: Sergy пишет: RESTSCREEN() возвращает вместо треугольника знак вопроса. Самодостаточный пример в студию, как говорится.

Dima: Sergy А вот так будут BAD ? ;) [pre2] proc main local csave local csave1 local i cls for i=1 to 10000 @ 10,10 say chr(16) color "gr+/r" csave:=savescreen(10,10,10,10) if left(csave,1)#chr(16) ? "Bad Savescreen " wait endif @ 10,10 say " " color "n/n" restscreen(10,10,10,10,csave) csave1:=savescreen(10,10,10,10) if left(csave1,1)#chr(16) ? "Bad Restscreen" wait endif next return [/pre2]

Sergy: AlexMyr пишет: Самодостаточный пример в студию, как говорится. Если-бы было все так просто... Из нескольких сотен вызовов SAVESCREEN/RESTSCREEN все работает ровно. Заковыка только в одном-единственном. Может еще где есть в программе - там вызовов десятки, если не сотни разбросаны. Ведь все происходит довольно быстро: SAVESCREEN - диалог - RESTSCREEN и практически сразу идет перепрорисовка меню. Заметить сложно. Пока вычислил один, но совершенно точно - врет... Либо глюк. Dima пишет: Sergy А вот так будут BAD ? Вечером смогу ответить.

PSP: Sergy пишет: Заковыка только в одном-единственном Пошагово выполнить программу. Может там действительно перед выполнением savescreen() знаки вопроса на экране.

Sergy: Dima пишет: Sergy А вот так будут BAD ? Не очень понял смысла кода (память/видеоадаптер проверялся что-ли...), но ни одной надписи "Bad savescreen" не получил.

Dima: Sergy Думаю где то твой косяк , просто подумай где он. У меня тоже при переводе программы на Harbour c Сlipper был глюк который не мог долго поймать. Психовал даже маленько ;) Но поймал. PS на форуме таких примеров при "переводе" достаточно, о якобы глюках Harbour.

Sergy: PSP пишет: Пошагово выполнить программу. Так и сделал. И акуел, если честно: [pre2] FUNC Main() LOCAL i,sx,cBuffer1,cBuffer2 REQUEST HB_LANG_RU866 REQUEST HB_CODEPAGE_RU866 HB_LANGSELECT("RU866") HB_CDPSELECT("RU866") CLEAR SCREEN sx:="" FOR i:=1 TO 30 sx += CHR(i) NEXT i @ 10,10 SAY sx cBuffer1 := SAVESCREEN(0,0,MAXROW(),MAXCOL()) INKEY(0) RUN("dir >nul") // Проблема оказалась тут... cBuffer2 := SAVESCREEN(0,0,MAXROW(),MAXCOL()) RESTSCREEN(0,0,MAXROW(),MAXCOL(),cBuffer2) @ 12,10 SAY "Two screens are " + IIF(cBuffer1 == cBuffer2,"EQUAL","DIFFERENT") INKEY(0) RETURN [/pre2] Загвоздка оказалась в команде RUN. Как она может повлиять на SAVESCREEN() - ума не приложу.

Pasha: Sergy пишет: Загвоздка оказалась в команде RUN. Как она может повлиять на SAVESCREEN() - ума не приложу. Харбор-программа разделяет консоль с внешним приложением (cmd.exe), которое изменяет какие-то параметры консоли.

Dima: Sergy Вместо RUN поюзай hb_processrun , WAPI_ShellExecute , EXECANDWAIT

Pasha: Делаем тест: #include "hbgtinfo.ch" proc main Local i, j, cc REQUEST HB_CODEPAGE_RU866 REQUEST HB_LANG_RU866 hb_cdpSelect( "RU866" ) cls //hb_gtinfo(HB_GTI_COMPATBUFFER, .f.) for i := 0 to 15 cc := '' for j := 0 to 15 cc += Chr(i*16 + j) next @ i, 0 say cc next cc := SaveScreen(0,0,15,15) RestScreen(0,20,15,35,cc) run('dir >nul') cc := SaveScreen(0,0,15,15) RestScreen(0,40,15,55,cc) wait retu На экране видим бяку на месте кодов меньше 32 А теперь фокус-покус: добавляем вызов hb_gtinfo(HB_GTI_COMPATBUFFER, .f.) и все исправляется. Только при этом буфер для savescreen/restscreen будет в 2 раза больше.

PSP: Ну да: HB_GTI_COMPATBUFFER /* Use DOS CGA/EGA/VGA character/attribute buffer in SAVE/REST SCREEN */

Sergy: Pasha пишет: На экране видим бяку на месте кодов меньше 32 А теперь фокус-покус: добавляем вызов hb_gtinfo(HB_GTI_COMPATBUFFER, .f.) и все исправляется. Только при этом буфер для savescreen/restscreen будет в 2 раза больше. Пока остановился на замене #define RUN(x) HB_ProcessRun(x) - SAVESCREEN заработал нормально. Понятно, что под Windows памяти дофига - но жалко же какой смысл ее транжирить...

Sergy: Sergy пишет: #define RUN(x) HB_ProcessRun(x) Так не пойдет - только что наступил на грабли: не выполняются команды shell - dir, copy, ren и тп... При этом не выдаются никакие сообщения об ошибке. Просто игнор и всё. Нужно вот так: #define RUN(x) HB_ProcessRun("cmd /c "+x) буффер не портится и команды command shell выполняются.

Dima: Sergy пишет: При этом не выдаются никакие сообщения об ошибке. Просто игнор и всё. Оно пишется в 3-й параметр этой функции если его указать Sergy пишет: не выполняются команды shell - dir, copy, ren и тп... А зачем ? Все это можно делать средствами Harbour

nick_mi: А почему нельзя сохранять экран ДО команды RUN ? Так было бы логичнее.

Sergy: nick_mi пишет: А почему нельзя сохранять экран ДО команды RUN ? Так было бы логичнее. Изначально вопрос стоял так: в процессе перехода с Clipper на Harbour были устранены шероховатости и программа была запущена в работу на предприятии. Все возникающие в процессе работы вопросы решались, за исключением непонятки, "портившей" символы с кодом ниже CHR(32) при восстановлении на экран. После детального изучения вопроса (а версии возникали самые разные - они описаны тут, на пред. страницах) выяснилось, что уже SAVESCREEN возвращает "испорченный" буфер экрана. Пошаговое выполнение программы привело к выяснению причины - ею оказалась команда RUN(). Понятно, что анализировать сотни/тысячи строк кода и выяснять, где идет RUN(), а потом SAVESCREEN() вряд-ли имеет смысл и решение с #define кажется мне на сегодня вполне достаточным.

Sergy: Dima пишет: А зачем ? Все это можно делать средствами Harbour Безусловно. Но речь идет о запуске тысяч строк кода Clipper под Harbour, а не его переделке "с учетом возможностей". А в Clipper, к примеру, невозможно было работать нормально с каталогами/файлами, не соответствующими формату 8.3. Да и в Harbour сейчас проще записать RUN("del local\*.dbf >nul") чем городить такой огород: dim:=DIRECTORY(cPath,"*.dbf") ; AEVAL(dim,{|x| cPath+x[F_NAME]...}).

Sergy: Решил поднять старую тему: http://clipper.borda.ru/?1-20-0-00000475-000-0-0-1208757116 Речь в ней идет о DIRTYREAD/TURBOREAD/DBOI_READLOCK Подскажите плиз - к каким все-таки результатам приводит включение этого "ускорителя" ? Общая ситуация такая: есть куча пользователей, которые что-то пишут в таблицу с продажами. Есть пара пользователей, которые на основании таблицы продаж в READONLY режиме хотят построить отчет. Вот тут я немного не понял, чем все кончилось, а тема закрыта: если я у этой пары пользователей ("читателей") включу dbOrderInfo(DBOI_READLOCK,,, .t.) - что, помимо ускорения выборки, произойдет? Если в таблице за время построения отчета появятся какие-то записи - "читателям" по барабану: отчеты обычно строятся за прошлые периоды, изменение которых юзерам запрещено программно. Будут ли ошибки у "читателей" таблицы? Или у "писателей" в неё? Спасибо.

petr707: Если технология - файл-серверная и данные за прошлые периоды не изменяются, зачем нагружать доступ ко всей базе "грязным" чтением ? Можно сверить текущую базу с предыдущей локальной выборкой( копией ) и строить отчеты по локальной копии продаж, не нагружая рабочую базу. Создание файла локальной копии происходит гораздо быстрее и менее напряжно, чем подготовка отчетов по общей базе, и в общем случае, затраты ресурсов и времени на создание локальной копии окупаются. Заодно - получается точная фиксация "точки отсечения" - на какой момент фиксировано состояние продаж. if local_file_not_exist or local_file_is_old ;use .. shared readonly; copy to (local_file) for ..; close ..

Pasha: Sergy пишет: Вот тут я немного не понял, чем все кончилось, а тема закрыта: если я у этой пары пользователей ("читателей") включу dbOrderInfo(DBOI_READLOCK,,, .t.) - что, помимо ускорения выборки, произойдет? Если в таблице за время построения отчета появятся какие-то записи - "читателям" по барабану: отчеты обычно строятся за прошлые периоды, изменение которых юзерам запрещено программно. Будут ли ошибки у "читателей" таблицы? Или у "писателей" в неё? DBOI_READLOCK касается только выборки по управляющему индексу. Если этот параметр включен, то на время включения другие клиенты не смогут ничего ни прочитать, ни записать в рабочую область, т.к. индекс блокируется для чтения. Внешне это будет выглядеть как "зависание" клиента. Поэтому использовать эту опцию надо аккуратно, и на очень непродолжительное время. Можно сделать тест: dbOrderInfo(DBOI_READLOCK,,, .t.) wait и попробовать с другого клиента выдась go top/skip, и посмотреть, что получится. Ничего хорошего, естественно. Это все проблемы файл-сервера. Для клиент-сервера вроде ads/letodb такой проблемы нет в принципе.

Sergy: petr707, Pasha Мысли понятны. С letodb скоро разберусь. И загрузку локально для справочников я провожу всегда, практически с первого дня написания программы. Для большой кучи отчетов (в начале месяца, например) есть функция "работать локально" - через 5-7 минут ожидания (пока вся база скопом копируется в локальную папку) - программа работает с ней, как ни в чем не бывало, но в READONLY - чтобы никто не навыписывал по забывчивости накладных. А вот если юзеру нужно всего один-два отчета, не окажется ли процесс "копирование всей таблицы продаж + локальная индексация" длительнее, чем просто чтение нужного периода по индексу ? Т.е. овчинка не будет стоить выделки... Думал, что DBOI_READLOCK поможет ускорить чтение по индексу. Спасибо.

Andrey: Уже перешел на Харбор ! Поздравляю ! Sergy пишет: А вот если юзеру нужно всего один-два отчета, не окажется ли процесс "копирование всей таблицы продаж + локальная индексация" длительнее, чем просто чтение нужного периода по индексу ? Для различных выборов из баз, делай условную индексацию по уже сформированным индексам. Отчеты будут строиться влет, даже не успеешь заметить... Здесь на форуме обсуждалось это, и не раз.

petr707: для каждой задачи можно проверить и выбрать подходящую схему.. set order to 0; copy to () for...; index on ... может оказаться быстрее чем index on ...; copy to () for...;

Pasha: Sergy пишет: Думал, что DBOI_READLOCK поможет ускорить чтение по индексу. Сергей, я подзабыл эти вещи, и неправильно написал: DBOI_READLOCK блокирует выборку на запись с других клиентов, а не на чтение. А так да, когда я использовал DBFCDX, установка DBOI_READLOCK меня реально выручала. В сетевом окружении скорость выборки возрастала многократно. Что же касается остальных вариантов, то надо иметь в виду: все эти приемы: динамическое построение индекса, или индекса с условием, или копирование таблицы с set order to 0 для больших таблиц неприемлемы, поскольку предполагают цикл по всем записям, что быстрым быть не может. Надо применять обычное решение: иметь правильный набор индексов для возможных выборок, и использовать их. Для файл-сервера DBOI_READLOCK реально помогает. Проблем из-за его использования у меня не было. Только, как я отмечал, его надо использовать аккуратно.

Sergy: Pasha пишет: DBOI_READLOCK блокирует выборку на запись с других клиентов, а не на чтение. Требуется уточнение: блокирует именно те записи, по которым идет чтение или целиком запись в индексный файл ? Тк первый вариант для меня подходит, а второй - нет.

Sergy: Andrey пишет: Для различных выборов из баз, делай условную индексацию по уже сформированным индексам. Не очень знаком с условной индексацией, если честно... Направьте плиз на путь истинный. Вот допустим, у меня есть таблица продаж: date D8 // дата продажи stk1 N5 // продавец stk2 N5 // покупатель code C10 // код товара num N10 // кол-во price N10.2 // цена И два индекса: 1) по CODE (чтобы быстро находить нужный товар в куче продаж) 2) по DATE (чтобы быстро найти нужный период для отчета) Для построения отчета использую таблицу продаж только со вторым индексом в режиме READONLY Как условная индексация может тут помочь ?

Pasha: Sergy пишет: Требуется уточнение: блокирует именно те записи, по которым идет чтение или целиком запись в индексный файл ? Блокирует весь индекс, то есть любое изменение. Причем ошибка не возникает, клиент просто ждет, пока другой клиент не отпустит индекс.

Andrey: Sergy пишет: Для построения отчета использую таблицу продаж Какая таблица ? Какие критерии построения отчета ? Дайте примеры что ищите...

Pasha: Sergy пишет: Как условная индексация может тут помочь ? Никак. Каждый инструмент хорош для своих целей. Условная индексация применяется, если надо полностью исключить из индекса данные по некоторому условию.

Sergy: Вопрос. Существует ли какой-нибудь способ "снести" работающую программу на Harbor с клавиатуры с установленным SETCANCEL(.F.) ? Суть в следующем: есть довольно сложный участок кода, приводить его здесь в качестве "самодостаточного примера" нет никакой возможности: куча RELATION, FILTER по нескольким открытым таблицам: типичная работа юзера: открыть накладную, нажать Insert, выбрать (отфильтровать) нужный товар, нажать ENTER, ввести нужно кол-во -> товар добавляется в накладную. Опять начались необъяснимые вылеты программы: ни стандартный обработчик ошибок, ни hb_out.log ничего не дают: в обоих случаях пусто. Программа просто схлопывает окно без малейшего сообщения. По диспетчеру задач утечек памяти (как было с ошибками 9ххх) точно нет. Зависаний, подтормаживаний - тоже. Все летает, потом - бац - окна нет. Сделал тест: в основном цикле обработки нажатий юзера сделал примерно следующее: при нажатии K_ALT_F1 в буфер клавиатуры засылаются типичные нажатия на клавиши юзера (K_INS + случайная последовательность цифр (типа, поиск товара) + K_ESC (отмена) или K_ENTER (выбор) + заново K_ALT_F1 (чтобы зациклить процесс). В ходе чего тупо увеличивается счетчик и при помощи STRFILE() сбрасывается в локальный файл, чтобы понять, сколько раз цикл проработал. В результате: цикл отрабатывает уже несколько тысяч раз - гораздо больше, чем за день набивает среднестатистический юзер - все ровно. И в локальной базе на компе с Harbour и в реальной сети. Может там какой CTRL в комбинации с ALT позволяет сделать что-то типа ALT_C при SETCANCEL(.T.) ?

petr707: Добавить режим работы программы (по настройке) - запись в лог всех действий юзеров , с указанием места в коде программы, до отдельных клавиш клавиатуры можно не детализировать. Можно поймать момент времени, когда и в каком месте кода произошло прекращение работы. Применяется ли EXIT procedure и что фиксируете при нормальном завершении? Можно организовать отдельный поток ( с логированием) который просто через интервал ( 10 сек) в этот же лог работы юзеров будет скидывать состояние некоторых ключевых параметров состояния

Sergy: petr707 пишет: Применяется ли EXIT procedure и что фиксируете при нормальном завершении? При запуске программы из mem-файла берется error_counter (изначально равный -1, увеличивается на единицу и сохраняется назад в mem-файл. При нормальном завершении уменьшается на единицу и еще раз сохраняется в mem-файл. Во время работы значение err_count мониторится. Если не равно нулю - значит был вылет. Можно организовать отдельный поток ( с логированием) который просто через интервал ( 10 сек) в этот же лог работы юзеров будет скидывать состояние некоторых ключевых параметров состояния Спасибо за идею. Организовывать MT для задачи, которая и так себя нестабильно ведет, наверное не совсем верно. Попытаюсь решить через SaveConsole()/RestConsole() - мою обертку для SAVESCREEN()/RESTSCREEN() - они вызывается чаще всего и регулярно при входе/выходе в большинство процедур.

AlexMyr: Sergy пишет: ни стандартный обработчик ошибок, ни hb_out.log ничего не дают: в обоих случаях пусто. Т.е. hb_out.log появляется, но он пустой? А про обработчик ошибок что имеется ввиду что тоже пустой? Можно пересобрать harbour c опцией: ## Memory statistics/tracking Build Harbour with: HB_USER_CFLAGS=-DHB_FM_STATISTICS потом пересобрать прогу и смотреть появится ли fm.log (вроде так) при очередном падении, если да, то смотреть что там.

petr707: Есть еще идеи 1) Если всю программу обернуть в begin..recover.. end то можно обнаружить некорректно перееопределенный ERRORSYS begin sequence ... all_program() recover using oError // В этой секции ? " Undefined error" end sequence 2) MT тем и хорош, что можно в поток обернуть проблемный вызов, и если он грохнется, основной поток будет жить и сможет разобраться,почему поток свалился. 3) Аналогично пункту 1 - почти весь код оборачивается во второй поток, в главном -только хорошо отлаженная диагностика свала второго потока

Sergy: AlexMyr пишет: Т.е. hb_out.log появляется, но он пустой? Сейчас вижу, что я некорректно выразился. Имелось в виду, что hb_out.log не появляется. А про обработчик ошибок что имеется ввиду что тоже пустой? Еще с давних времен я сделал свой обработчик ошибок, который при запуске программы устанавливается и больше не меняется. В случае возникновения программных ошибок, он выводит сообщение на экран и дублирует в файл, вместе со стеком вызовов, номерами строк, состоянием памяти, открытыми таблицами и тп. При следующем успешном запуске программы этот файл сливается в каталог с dbf таблицами - и не вставая с кресла можно понять, что именно, где, у кого и когда именно произошло. Для отлова программынх ошибок - самое то. Так вот в данном случае обработчик тоже "ни гу-гу".

Sergy: petr707 пишет: Есть еще идеи Хм... надо подумать в этом направлении.

Sergy: Поднял лог редактирований исходников и сравнил с ростом "неожиданных вылетов", которые начались в начале этой недели. Из значительных изменений, сделанных в программе было: #define RUN(x) HB_ProcessRun("cmd /c "+x) Вчера вечером отменил этот код, сегодня держу пальцы крестиком, но половину рабочего дня вылет был один раз и только на одной машине.

Sergy: Попутно возник еще вопрос. Есть dbf таблица на сервере с одной записью. Каждая машина в свой отдельный файл скидывает в нее свое состояние: стек вызовов, снимок экрана, дату/время и тп - как раз для диагностики происходящих вылетов. Вызов происходит в процессе FT_OnTick() каждые 10 секунд. Я на своем компе открываю мониторинг и вижу, что происходит на других компах. Обратил внимание, что дата модификации этого dbf файла не совпадает со штампом времени, в который сделана запись. Например: я смотрю у юзера состояние, присланное в 18:02, а сам файл имеет 4 штампа: [pre2] Far CTRL-A: ДД.ММ.ГГГГГ чч:мм:сс,мс Время последней записи: 20.09.2013 16:31:46,158 Время создания: 20.09.2013 15:25:15,916 Время последнего доступа: 20.09.2013 17:34:39,906 Время изменения: 20.09.2013 16:31:46,158 [/pre2] Почему уже полтора часа (с 16-30) не обновляется "время изменения" ? Может, до тех пор, пока пишущая программа не закроет эту таблицу не произойдет изменение ? Но почему тогда не меняется "время последнего доступа", если я смотрел только что с другого компа ? Раньше не обращал внимания на такие вопросы и мне кажется, в Clipper все было предельно четко: прошла запись - атрибуты файла соотв. образом изменились. Был лаг из-за небольшого отставания/спешки часов в ntvdm машине - но это было понятно хоть почему.

Dima: Sergy Где то поднимался на форуме такой вопрос , попробуй поиск помучать.

Pasha: Sergy пишет: Почему уже полтора часа (с 16-30) не обновляется "время изменения" ? Современные ОС еще не так чудят. 5 минут назад: Win7. Делаю xml-файл с помощью классов А.Кресина. Размер - 1.5М. Штатно закрываю его на локальном диске посредством oXml:Save( cFile ) Закрываю программу, перехожу в фар. Фар показывает его размер - 0 байт. Открываю его редактором, вьювером. Файл создан нормально, но его размер - 0. Только после копирования файла на другой диск исходный файл получил размер. Не верю своим глазам (изыди, нечистый). Плюю через левое плечо. Удаляю файл и проделываю все по новой. Размер появляется сразу. Изгнание беса помогло.

Sergy: Еще вопрос. Под Clipper работали сочетания клавиш ALT+цифры. Иногда, в некоторых местах программы довольно удобно было поставить "специальную" метку в реквизитах клиента, описании и тп. Например, "сеточка" ALT+1+7+6, "квадратик" ALT+2+5+4 и тп. Как активировать подобный функционал в Harbour ?

PSP: Sergy пишет: Как активировать подобный функционал в Harbour ? Сейчас проверил, работает. Терминал GTWVT. Пример простейший: [pre2]FUNCTION Main() LOCAL c := " " CLS @ 0, 0 GET c READ QUIT[/pre2] В get-е появляются символы с набранными на цифровой клавиатуре кодами.

Dima: Sergy пишет: Как активировать подобный функционал в Harbour ? Ни чего не нужно активировать , все и так работает ALT + твой код на цифровой клавиатуре

Sergy: Эк меня приглючило. И действительно, работает... Оказывается, для Harbour главное, чтобы NumLock был включен. В Clipper (ntvdm) работало в любом состоянии NumLock. Только что проверил. Спасибо!

PSP: Sergy пишет: Оказывается, для Harbour главное, чтобы NumLock был включен. В Clipper (ntvdm) работало в любом состоянии NumLock. Только что проверил. Спасибо! Во как! Спасибо тоже! :)

Sergy: Подскажите плиз, уже намаялся: Вот, допустим, накосячил я где-то в исходнике (ENDIF забыл, ну или там DO / WHILE перепутал...) - возникает несколько десятков ошибок в цепочке. Компилятор выплевывает их всех, разумеется, на экране консоли виден только их "хвост". Как понять, с чего все началось ? Использую hbmk2 под Far. Пока временно приходится ставить высоту буфера экрана под 300 символов, компилировать и потом снова возвращать нормальные 25. Надоело...

petr707: hbmk2 test.hbp -otest.exe> build_test.log и смотреть log а лучше - выбрать среду разработки или редактор с вызовом компилятора

Sergy: petr707 пишет: hbmk2 test.hbp -otest.exe> build_test.log и смотреть log Разумеется, пробовал в первую очередь. Вот что в логе: hbmk2: Compiling Harbour sources... Harbour 3.2.0dev (r1308141636) Copyright (c) 1999-2013, http://harbour-project.org/ 100 200 300 400 500 600 700 Compiling 'main.prg'... 100 100 100 200 300 100 200 300 400 500 600 100 200 300 400 500 600 700 800 900 1000 1100 1200 1300 1400 1500 1600 1700 1800 1900 2000 2100 2200 2300 2400 2500 2600 2700 2800 2900 3000 3100 3200 3300 3400 3500 3600 3700 3800 57 errors No code generated.

petr707: hbmk2 ... 1> compile.log 2>error.log

Sergy: Возвращаясь к вопросу ускорения загрузки справочников с сервера в локальную папку: Sergy пишет: Речь в ней идет о DIRTYREAD/TURBOREAD/DBOI_READLOCK Подскажите плиз - к каким все-таки результатам приводит включение этого "ускорителя" ? ... petr707 пишет: для каждой задачи можно проверить и выбрать подходящую схему.. set order to 0; copy to () for...; index on ... может оказаться быстрее чем index on ...; copy to () for...; Поставил пару экспериментов в сети с таблицами, которые в данный момент активно используются юзерами. У меня код USE (cTable) READONLY // без индекса COPY TO (cLocalFile) CLOSE работает примерно в 50 раз медленнее, чем COPY FILE (cTable) TO (cLocalFile) и примерно в 70 раз медленнее, чем STRFILE(FILESTR(cTable),cLocalFile) Но третий способ почему-то не копирует файлы больше 30-40 мегабайт, хотя оперативной памяти явно с избытком в данном случае. Кто знает ограничения на длину строки? У кого какой результат в сравниваемых способах? С учетом того, что часто в локальной папке все равно нужно выстраивать индекс, ускорение получается в 5..10 раз. После перехода с Clipper на Harbour и так всё залетало, а тут получается вообще TwinPower Turbo...

SergKis: Sergy смотри http://clipper.borda.ru/?1-4-40-00000872-000-0-0

Sergy: SergKis пишет: Sergy смотри http://clipper.borda.ru/?1-4-40-00000872-000-0-0 Там идет сравнение различных функций копирования файлов, а у меня волосы дыбом встают от разницы между "файловым" COPY FILE TO и "табличным" COPY TO, которым всегда пользовался...

petr707: Посмотрите примеры обработки таблиц в памяти - скорость впечатляет, может и не потребуется копировать файлы Тэги поиска mem: hb_memio

SergKis: Sergy пишет:Там идет сравнение различных функций копирования файлов, а у меня волосы дыбом встают от разницы между "файловым" COPY FILE TO и "табличным" COPY TO, которым всегда пользовался... COPY TO FILE это __Copyfile() по ссылке gfilatov2002 пишет:По-видимому, Hb_fcopy() будет побыстрее, поскольку она использует буфер размером 65536 (против 8192 у функции __Copyfile()) COPY TO имеет смысл, если надо урезать по полям или условиям выборки сразу. В VO в COPY TO если задан только файл выполнялась FileCopy(...)

Sergy: Возник вопрос: нужен встроенный просмотр картинок, но под терминал GTWIN. Такое возможно ? Хочу отказаться от Irfan View, который нужен только для того, чтобы вывести одну картинку на экран (образец товара).

Dima: Sergy пишет: нужен встроенный просмотр картинок, но под терминал GTWIN Встроенный вряд ли и придется лепить отдельную прогу под GTWVT PS Тоже вывожу образцы товара но прога под GTWVT поэтому и проблем нет.

Sergy: Короче, я обессилел и нифига не понимаю... Месяц уже ищу причину ничем не объяснимых вылетов программы. Поступил следующим образом: расставил в "критических" местах команды ... Trace("before some action 1") ... do some action 1 ... Trace("after some action 1") ... do some action 2 ... Trace("after some action 2") ... Функция Trace просто сбрасывает дату+время+строчку в "свой" лог, чтобы не путать машины. Выяснил, что программа без единого сообщения падает на вот таком коде: [pre2] Trace("SelectFromStock(7): names2 relations cancelled") SELE amount IF (am_ord # 2) SET ORDER TO am_ord ENDIF SELECT(area) RestConsole(scr) sfs_filter_keeper := filter_str // private -->> module static KnowValue(KV_SFS_MODE,show_mode) // сохраняем режим Trace("SelectFromStock(8): before RETURN "+res) [/pre2] Или вот на таком: [pre2] Trace("SaleAddRec(5): work with "+value) s_code := value s_num := 0 s_sale_price := amount->sale_price s_buy_price := ROUND(amount->buy_sum / amount->num,0) IF (ABS(s_buy_price) < 0.0005) .OR. (amount->num==0) s_buy_price := amount->buy_price ENDIF Trace("SaleAddRec(5a): RUB buy price calculated, checking $") [/pre2] В среднем примерно в 3х случаях из тысячи на любом из пяти рабочих компьютеров, где эти операции происходят... Самое убийственное для меня в том, что до расстановки этих Trace вылеты были в среднем 10 раз на тысячу. Тысяча "чистых" отработок взяты не с потолка, это примерное количество строчек в накладных, соответствующее кол-ву "вылетов". Подобные вылеты "на ровном месте" происходят и в других местах программы. Расставлять там Trace() уже не понимаю, зачем... :( Короче, полный ппц какой-то - программа валится как карточный домик от малейшего дуновения... Пару раз при мне, лично сам видел - тупой зависон на ровном месте, программа ни на что не реагирует, загрузка одного ядра процессора под 100% - ничего кроме убийства приложения через диспетчер не помогает... :((( Подумал, может дело в компилере mingw, попробовал сделать hbmk2 myproject.hbp -comp=bcc (остался от версии 3.0.0) - Turbo linker не может найти библиотеку HBNF.LIB... не от версии 3.0.0 же ее брать... руки опускаются, черная дыра какая-то...

petr707: s_buy_price := ROUND(amount->buy_sum / amount->num,0) ... / amount->num ?! Можно смоделировать ошибку и проверить, как работает обработчик ошибок Если "..программа без единого сообщения падает " , то обработчика реально - нет. Вызовите где-нить рядом что-нить типа ... err_simulate() .. Function err_simulate() Local a:=0,b:=1 b:= 2/a return .t. Стремные места можно обрамить не trace , а break recover sequence BEGIN SEQUENCE with {|e| Break(e) } // segment RECOVER Trace("Erron in segment ..") END SEQUENCE При тупом зависоне 100% - ищем hb_out.log немерянного размера - там критическии свалы во множестве

Sergy: petr707 пишет: s_buy_price := ROUND(amount->buy_sum / amount->num,0) ... / amount->num ?! amount->num - целое числовое поле, вполне может быть нулем. Там чуть ниже проверка идет: IF (ABS(s_buy_price) < 0.0005) .OR. (amount->num==0) это алгоритм расчета закупочной цены товара: сумма закупки делится на кол-во в остатках. Если кол-во равно нулю (например, оформляется возврат) - берется цена последнего поступления. Остаток равен нулю примерно... в каждой 50й операции... Ведь с давних времен еще в Clipper повелось: [pre2] d:\Harbour sources\src\rtl\errsys.prg // By default, division by zero results in zero IF e:genCode == EG_ZERODIV .AND. ; e:canSubstitute RETURN 0 ENDIF [/pre2] Обработчик точно есть, он устанавливается в самом начале и исправно скидывает в лог полную информацию об ошибках. Но они точные и четкие: код ошибки, стек вызовов, номера строк, состояние памяти, список открытых таблиц и тп. petr707 пишет: При тупом зависоне 100% - ищем hb_out.log немерянного размера - там критическии свалы во множестве Нету. У меня по умолчанию локальные report.log (сообщения об ошибках, туда-же идет трассировка) и hb_out.log сливаются при каждой команде CloseAll() на сервер под "своим" именем, зависящим от "имени" машины в сети.

petr707: // By default, division by zero results in zero IF e:genCode == EG_ZERODIV .AND. ; e:canSubstitute TRACE("zerodiv was !") RETURN 0 ENDIF Если увидите Trace - то работает обработчик, но позволять этого в качестве рабочих вычислений - нельзя. При неудачном раскладе такое вольное обращение с делением на 0 - может зациклить процесс.

petr707: hb_out. log - легко упрется в 2 Гига - и тогда ничего никуда не сольется

Sergy: petr707 пишет: TRACE("zerodiv was !") Хм. поставлю. Уверен, что будут трассировки. Понимаю, что в математике делить на ноль нельзя. Но почему нельзя этого делать в Harbour ?? Это ведь стандартный текст обработчика, я его скопировал и дополнил дополнительной инфой.

Sergy: petr707 пишет: hb_out. log - легко упрется в 2 Гига - и тогда ничего никуда не сольется Эвона как... Поставлю проверку на это дело... Хотя не совсем понятно, чем помешают именно 2 гига... FAT ни на одной машине давно не используется - только NTFS.

petr707: IF (ABS(s_buy_price) < 0.0005) .OR. ABS(amount->num) <0.0005 s_buy_price := amount->buy_price else s_buy_price := ROUND(amount->buy_sum / amount->num,0) ENDIF

Sergy: petr707 пишет: Разве тяжело сделать аккуратнее ?! Вовсе нет. Сделаю. Прямо сейчас. Как попробовать другой компилер с Harbour 3.2.0 ?

petr707: Не уверен, что в поставке 3.2 есть BCC отладить - можно и на 3.0 ========= rem @echo off cls echo echo .. building P ... set HB_PLATFORM=win set HB_ROOT=C:\hb30 set HB_BIN_INSTALL=C:\h30\bin set path=%HB_ROOT%\bin;c:\borland\bcc55\bin;%path% %HB_ROOT%\bin\hbmk2.exe test_bcc.hbp -oTEST_bcc.EXE > build_.log ... ========== set HB_PLATFORM=win set HB_ROOT=C:\hb30 set HB_BIN_INSTALL=C:\hb30\bin set path=%HB_ROOT%\bin;C:\hb30\comp\mingw\bin;%path% %HB_ROOT%\bin\hbmk2.exe test_m3.hbp -oTEST_m3.EXE 1> build_m3.log 2>error_m3.log ..

Sergy: Поставил в обработчик трассировку: // By default, division by zero results in zero IF e:genCode == EG_ZERODIV .AND. ; e:canSubstitute TRACE(STR(++static_counter)+". Division by zero. ") RETURN 0 ENDIF Нажимаю на кнопку "Расчет заказа по результатам торговли" - в логе 12809 сообщений...

petr707: примеры, нужно затачивать под себя =================test_bcc.hbp=== # -platform=win -compiler=bcc #-inc -info -trace #further link options -W3 -es2 #-mt # compile options #-m #-n #-es0 -w0 #-b # libs -liphlpapi -lxhb -lhbxpp -lhbmzip -lvfw32 -lhbwin -lhbct -lhbrtl -lhbvm -lhbnf #-llibpng -lhbtip -lhbmisc -std -gtwvt -prgflag=-D_HBMK_ -DIN_NET -DHARB3 -ldflag=-aa -nohbc #-run #source TEST.PRG ... ===============test_m3.hbp== # -platform=win -compiler=mingw #-inc -info -trace #--hbinfo -quiet -oTEST_m3.EXE -workdir=C:\temp #further link options #-W3 #-es2 #-mt -ldflag=-Wl,--allow-multiple-definition # compile options #-m #-n #-es0 -w0 #-b # libs ....

Sergy: Я вот чего думаю - может придумать какой-нить "стресс-тест", который позволит по максимуму нагрузить подсистему Harbour/С и выяснить - в чем проблема? Может дело в железе/памяти/системных ошибках на конкретной машине? У кого-нить есть опыт построения подобных вещей? Первая мысль - построить массив на пару миллионов записей (учесть свободную память перед этим, разумеется) и погонять как следует по нему: сложить/вычесть/посчитать контрольные суммы... Может таблицу какую сгородить и прокрутить ее по сети...

Pasha: Сергей, ну вкратце расскажите, решена ли проблема со сваливанием программы ? Помогли советы в harbour users list ? Насколько я понял, после внесения правок в реестр (обычный трюк для клиппера) проблема исчезла ? Или это только в тестах ?

AlexMyr: Pasha пишет: Может дело в железе/памяти/системных ошибках на конкретной машине? Если проблема в этом, то были б "синие екраны смерти виндовс", плюс к этому создаются дампы памяти, по к-м можно узнать причину. Т.к. вылетала эта прога написанная на clippere, то проблема в коде, как уже было сказано в harbour users list исходников никто не видит и потому все работают в этом случае телепатами. Как я понимаю исходных кодов много, и то что все это завелось под harbour, то это большой плюс harbour-у, а код надо пересмотреть, оптимизировать, лишнее убрать, и т.д...

Sergy: Pasha пишет: Сергей, ну вкратце расскажите, решена ли проблема со сваливанием программы ? Помогли советы в harbour users list ? Насколько я понял, после внесения правок в реестр (обычный трюк для клиппера) проблема исчезла ? Или это только в тестах ? Спасибо, что не остались равнодушны. Сегодня под вечер три раза сработала вот эта мышеловка: [pre2] FUNC Main() ... some inits BEGIN SEQUENCE MainMenu() RECOVER OutReportLog("Unexpected break in the sequence catched") END SEQUENCE ExitProgram() RETURN // Main() [/pre2] Теперь вот сижу, ломаю голову, как понять, откуда она вызвана. Получается, что ProcStack() в RECOVER блоке уже ничего не показывает. Посмотрел - в std.ch нет команды переопределения BREAK <x>, например, на функцию Break(x). У меня в некоторых местах есть, к примеру, BREAK 1, BREAK 2 и потом - RECOVER USING nValue. Хочу сделать что-то наподобие #command BREAK <x> => OutReportLog("Break call"+ProcStack(,,TRUE,CRLF)) ; Break(<x>) Но не уверен в синтаксисе... hbmk2 завис на компиляции одного из *.prg файлов после внесения таких изменений в общий для всего проекта *.ch ...

Sergy: AlexMyr пишет: Если проблема в этом, то были б "синие екраны смерти виндовс", плюс к этому создаются дампы памяти, по к-м можно узнать причину. Т.к. вылетала эта прога написанная на clippere, то проблема в коде, как уже было сказано в harbour users list исходников никто не видит и потому все работают в этом случае телепатами. Как я понимаю исходных кодов много, и то что все это завелось под harbour, то это большой плюс harbour-у, а код надо пересмотреть, оптимизировать, лишнее убрать, и т.д... А чего толку от 2.5 мегабайт исходников? Я их сам 15 лет уже вижу практически каждый день, почти всё наизусть помню - а у меня на рабочем месте ни разу!!! за все время такого вылета не было... Да и на половине рабочих мест предприятия - тоже.

AlexMyr: Sergy пишет: А чего толку от 2.5 мегабайт исходников? Ну да, че толку, винда ж глючит, а она у вас лицензионная?

Sergy: AlexMyr пишет: Ну да, че толку, винда ж глючит, а она у вас лицензионная? Честно говоря, не очень понял связи.

AlexMyr: Sergy пишет: Честно говоря, не очень понял связи. Вы говорите о вылетах своей проги и не придаете никакого значения исходникам Sergy пишет: А чего толку от 2.5 мегабайт исходников? принимая их за валидный и оптимальный код. За эти дни можно было уже в каждую ф-ю и процедуру вначале и в конце вписать "начало работы такой-то func", "конец работы такой-то func" все вывести в лог файл и каждый день парсить его на предмет аномалий. Я говорю о том, что вы один на один со своей проблемой, давая только куски кода, где все вроде нормально, а в общем контексте имете то, что имете, и об этом говорили в user list.

Dima: AlexMyr пишет: и об этом говорили в user list Ссылку напомни плиз

Sergy: AlexMyr пишет: принимая их за валидный и оптимальный код. За эти дни можно было уже в каждую ф-ю и процедуру вначале и в конце вписать "начало работы такой-то func", "конец работы такой-то func" все вывести в лог файл и каждый день парсить его на предмет аномалий. Я говорю о том, что вы один на один со своей проблемой, давая только куски кода, где все вроде нормально, а в общем контексте имете то, что имете, и об этом говорили в user list. Честно говоря, не понимаю, с чего Вы так решили. Вовсе не считаю свой код валидным и оптимальным. Ищу ошибку. Сложную. По поводу "вставить в каждую функцию трассировку" - возможно и дойдет до этого, куда деваться? Пока хочу разобраться с этой болячкой путем наименьшего затрагивания исходников. Поскольку в 99.999% нажатий на кнопки клавиатуры все происходит так, как положено. И по-хорошему, можно было-бы забить на 2-3 вылета в день. Раньше вылетало чаще. Ну подумаешь, делов-то... Но я так не могу. Спасибо за поддержку в любом случае.

AlexMyr: Sergy пишет: И по-хорошему, можно было-бы забить на 2-3 вылета в день. Раньше вылетало чаще. Ну подумаешь, делов-то... Не хочу Вас обидеть, но у юзеров должны быть крепкие нервы в такой ситуации на протяжении 15 лет.

AlexMyr: Dima пишет: Ссылку напомни плиз пересмотрю user list, покажу, но там прямо так не сказано.

AlexMyr: AlexMyr пишет: Dima пишет: цитата: Ссылку напомни плиз пересмотрю user list, покажу, но там прямо так не сказано. Вот продолжение темы https://groups.google.com/forum/#!topic/harbour-users/zTxmANrh2oU

Pasha: Sergy пишет: Сегодня под вечер три раза сработала вот эта мышеловка: Скорее всего это не наш загадочный случай, а обычная ошибка, которую поймал обрработчик. Можно немного видоизменить код: recover using oErr и в протокол выдавать параметры oErr, чтобы было понятно, что это за зверь.

Sergy: Pasha пишет: Скорее всего это не наш загадочный случай, а обычная ошибка, которую поймал обрработчик. Можно немного видоизменить код: recover using oErr и в протокол выдавать параметры oErr, чтобы было понятно, что это за зверь. А если это обычный BREAK, не завернутый в BEGIN SEQUENCE ... RECOVER ... END? Таких команд в тексте много, но все они предназначены для обработки критических ситуаций с таблицами, дисками и тп... Вчера полночи просматривал исходники - вроде все ровно... Пока сделал так: #command BREAK [<x>] => BreakList(<x>) BreakList() выведет стек вызовов включая себя самого и вызовет стандартный Break(x). В случае перехвата в Main() - будет нормальный ExitProgram. Поставил там-же еще Alert() с требованием вызвать админа или программера. В тексте программы сейчас включен отладчик, сырцы на флэшке. Если буду на месте в этот момент - надеюсь поймать. Спасибо.

Pasha: Для анализа ошибок открытия файла в протокол можно выдавать значение hb_osError(). Это код ошибки последней операции, который дает windows.

Sergy: Решил двинуться дальше, в сторону подключения мыши к изначально "клавиатурной" программе. Не то, чтобы очень нужно, но задают вопросы "а с планшета можно" ? Говорю - "можно, но неудобно, тк экранная клавиатура терминального клиента занимает пол-экрана". Но какие-то шаги в этом направлении пора делать... Практически все "окна" в программе рисуются "виртуально" при помощи @ a,b,c,d BOX ..., устанавливаются "временные" относительные координаты от начала текущего окна и осуществляется SAY ... GET. Мне нужно сделать так, чтобы при нажатии мышью за пределами определенного прямоугольника в буфер клавиатуры попала команда Esc, соотв. выбранный отчет/операция будут отменены. Подскажите пожалуйста - в каком направлении двигаться для адаптирования программы под мышь? Спасибо.

Sergy: И еще вопрос: перешел на GTWVT. Какие шрифты для работы с ним кто использует? Кроме "стандартных" Courier и Lucida Console разумеется. Очень хочется сделать похожим на вот это: Для себя "нашел" ещё удачными Consolas и Andale Mono. Какие вообще требования к шрифтам, которые можно подключить к GTWVT? Так понимаю, что шрифт должен быть OpenType и Unicode ? Может быть, где-то есть готовый список ?

SergKis: Sergy пишет:для адаптирования программы под мышь в каталоге test\mouse.prg, и поищи mouse в test\*.prg для начала.

SergKis: Sergy еще глянь test\wvtext.prg, может понравится

Dima: Sergy пишет: Может быть, где-то есть готовый список ? Скорее всего его нет а шрифты лучше брать моноширинные.

Andrey: Я сделал функцию для пользователей - выбор шрифта. http://file.qip.ru/arch/8e-shgP3/GTWVT-ChoiceFont-xHarbour.html

Sergy: Andrey пишет: Я сделал функцию для пользователей - выбор шрифта. Спасибо за пример.

Sergy: SergKis пишет: еще глянь test\wvtext.prg, может понравится Там 4 "импортных" моноширинных шрифта. Нужны "отечественные". Может кто использует ещё что-то, кроме перечисленных.



полная версия страницы