1. *========================================================================================
  2. *
  3. * Version: 2010-02Feb-20
  4. *
  5. *========================================================================================
  6. *
  7. * This program implements partial IntelliSense in VFP 6-9. To enable
  8. * IntelliSenseX, simply execute this program at any time when using
  9. * Visual FoxPro or put it into your startup program.
  10. *
  11. * To configure ISX please see the section just below the comment block.
  12. *
  13. * To stop IntelliSenseX run this program again and pass "QUIT" as a
  14. * parameter. Alternatively, you can simply remove the ON KEY LABEL
  15. * macros for the ALT+I and the "." key.
  16. *
  17. * Currently only IntelliSense for variable names is implemented. This
  18. * means that whenever you enter "m." in a MODIFY COMMAND window or
  19. * in a Method edit window, you get a list of all variables declared
  20. * in the current procedure. ISX doesn't parse the entire sourcecode
  21. * for memory variables, but only the current procedure or method and
  22. * only those variables listed in a LOCAL, PRIVATE, PUBLIC, LPARAMETER
  23. * and PARAMETER statement. ALT+I can be used to trigger this list.
  24. *
  25. * ALT+RIGHTARROW triggers a universal autocomplete function that tries to determine the
  26. * type of what you have entered and offers a list of all possible values.
  27. *
  28. * Please note that I haven't written this program as an excercise for
  29. * good coding styles <g>, rather as an excercise to see if
  30. * IntelliSense is possible within Visual FoxPro itself. Therefore
  31. * you won't find the Assertions you would otherwise find in my code.
  32. *
  33. *========================================================================================
  34. *
  35. * Acknowledgements
  36. *
  37. * Thanks to George Tasker for his really helpful documentation on the
  38. * FoxTools.Fll. You can download his ToolHelp.Hlp file from the
  39. * UniversalThread and the CompuServe MSDEVAPP forum. George also made
  40. * some suggestions to improve this program.
  41. *
  42. * Also thanks to Ken Levy, who couldn't implement an inline Intelli-
  43. * Sense feature in his SuperCls and thereby convinced me that there
  44. * must be a way to do it, even only for the purpose of doing
  45. * something that Ken Levy couldn't do. <bg>
  46. *
  47. * Thanks to all the folks that posted me bug reports, especially
  48. * Frank Cazabon. Thanks to Gerry Hughes for correcting the typos in
  49. * my comments.
  50. *
  51. * Louis D. Zelus added a nifty feature to my version to make ISX
  52. * even more useful. Thanks for that! The code based on his work is
  53. * marked with "LDZ:".
  54. *
  55. * Sietse Wijnkler added a lot of new cool features: He added the
  56. * ability to distinguish different types that all are triggered by
  57. * a period and the code to display variables, object properties and
  58. * field names. Code based on his work is marked with "SW:".
  59. *
  60. * J黵gen "wOOdy" Wondzinski pointed out that special characters like
  61. * "�" are valid variable names and IsAlpha() returns .T. for them.
  62. * Therefore any of these characters is detected by ISX, as well.
  63. *
  64. * Tamar E. Granor and Peter Steinke, both requested the list DEFINE
  65. * features which is why I finally added it.
  66. *
  67. * Thanks to Eddy Maue for his contributions:
  68. *
  69. * Ce qu'ile fait de plus maintenant
  70. * - Alt-Q pour arrer Isx
  71. * - Alt-Q pour redemarrer Isx
  72. * - Ouvre automatiquements :
  73. * -Les tables prentes dans les rertoires courants et de recherches
  74. * (set path to)
  75. * -Les vues prentes dans le projet actif
  76. * -Les query prents dans les rertoires courants et de recherches
  77. * (set path to)
  78. * Petit point ne pas nliger. Le curseur produit par le fichier
  79. * MyQuery.qpr doit re du me nom que le fichier
  80. *
  81. * In English:
  82. *
  83. * - ALT+Q enables/disables ISX
  84. * - files are opened automatically:
  85. * - tables available in the current directory or the search path (SET PATH TO)
  86. * - Views available in the current project
  87. * - Queries available in the current directory or the search path (SET PATH TO)
  88. * Minor, but important restriction: The cursor created by the query program
  89. * must have the same alias as the filename.
  90.  
  91. * Mike Yearwood added supported for maximized editing windows which caused a lot
  92. * of flickering everytime the popup came up.
  93. *
  94. * Thanks to all those who pointed out bugs in ISX's releases:
  95. *
  96. * - Nina Schwanzer
  97. * - Del Lee
  98. * - Pamela Thalacker
  99. * - Christophe Chenavier
  100. * - Aragorn Rockstroh
  101. * - Claude Hebert
  102. * - Jens Kippnich
  103. * - Stefan W黚be
  104. *
  105. *========================================================================================
  106. *
  107. * This program has been written in 1999-2005 by Christof Wollenhaupt
  108. * and is placed into Public Domain. You can use the entire
  109. * code or parts of it as you like in any private or commercial
  110. * application. None of the contributors to this programm can be hold
  111. * liable for any damage or problems, using this program may cause.
  112. *
  113. * If you added a new feature, please let me know. If you want I add
  114. * your feature to my master copy of ISX to let others use your
  115. * feature, as well. Please note that since the entire program is
  116. * placed into Public Domain, this places your code into Public
  117. * Domain, as well. Of course, your contributions are acknlowdeged in
  118. * the comment at the beginning of this file.
  119. *
  120. *========================================================================================
  121. *
  122. * Known problems:
  123. *
  124. * - So far ISX has not been tested with different Display appearance
  125. * settings, like wider scrollbars or form borders, large fonts and
  126. * the like. Some values are hardcoded and might be wrong for non-
  127. * standard Windows settings.
  128. *
  129. * - When you enter a period into a textbox, the cursor is set to the first character of
  130. * the textbox and then the period entered. If SelectOnEntry is true, everything is
  131. * replaced by the period. This is caused by a bug in VFP that makes all ON KEY LABEL
  132. * behave this way. You can disable this behavior by commenting out the lines starting
  133. * with "ON KEY LABEL .". In this case, you must use ALT+I or ALT+RIGHTARROW do expand
  134. * the variable.
  135. *
  136. *========================================================================================
  137.  
  138. *========================================================================================
  139. * Configuration.
  140. *
  141. * Over the time I got many enhanced versions of ISX, many of which include new hotkeys.
  142. * To give everyone control over the hotkey assignment and to disable/enable particular
  143. * features, I added the following configuration section. By commenting out a #DEFINE, you
  144. * disable a particular feature. Changing the value changes the hotkey.
  145. *
  146. *========================================================================================
  147.  
  148. #DEFINE EXPAND_VARIABLE ALT+I
  149. #DEFINE DOT_ACTIVATION .
  150. #DEFINE LIST_ALL ALT+RIGHTARROW
  151. #DEFINE TOGGLE_ISX ALT+Q
  152.  
  153. *========================================================================================
  154. * Main program
  155. *========================================================================================
  156. Lparameters tcAction, tcParam, tcParam2
  157.  
  158. Do Case
  159. Case Vartype(m.tcAction) == "L"
  160. InstallISX()
  161. Case Upper(Alltrim(m.tcAction)) == "AUTOCOMPLETE"
  162. Push Key Clear
  163. AutoComplete( m.tcParam, m.tcParam2 )
  164. Pop Key
  165. Case Upper(Alltrim(m.tcAction)) == "QUIT"
  166. UninstallISX()
  167. Endcase
  168.  
  169. Return
  170.  
  171. *========================================================================================
  172. * Activates the hotkeys.
  173. *========================================================================================
  174. Procedure InstallISX
  175.  
  176. Local lcISXProgram
  177. lcISXProgram = ["] + Sys(16,Program(-1)-1) + ["]
  178. #IFDEF EXPAND_VARIABLE
  179. On Key Label EXPAND_VARIABLE Do &lcISXProgram With "AUTOCOMPLETE", "VAR", ""
  180. #ENDIF
  181. #IFDEF DOT_ACTIVATION
  182. On Key Label DOT_ACTIVATION Do &lcISXProgram With "AUTOCOMPLETE", "VAR,OBJ,TABLE", "."
  183. #ENDIF
  184. #IFDEF LIST_ALL
  185. On Key Label LIST_ALL Do &lcISXProgram With "AUTOCOMPLETE", "", ""
  186. #ENDIF
  187. #IFDEF TOGGLE_ISX
  188. On Key Label TOGGLE_ISX Do &lcISXProgram With "QUIT"
  189. Wait Window Nowait [ISX up and running... TOGGLE_ISX to quit]
  190. #ELSE
  191. Wait Window nowait "ISX up and running..."
  192. #ENDIF
  193. EndProc
  194.  
  195. *====================================================================
  196. * Deactivates the hotkeys.
  197. *====================================================================
  198. Procedure UninstallISX
  199.  
  200. Local lcISXProgram
  201. lcISXProgram = ["] + Sys(16,Program(-1)-1) + ["]
  202.  
  203. #IFDEF EXPAND_VARIABLE
  204. On Key Label EXPAND_VARIABLE
  205. #ENDIF
  206. #IFDEF DOT_ACTIVATION
  207. On Key Label DOT_ACTIVATION
  208. #ENDIF
  209. #IFDEF LIST_ALL
  210. On Key Label LIST_ALL
  211. #ENDIF
  212. #IFDEF TOGGLE_ISX
  213. On Key Label TOGGLE_ISX Do &lcISXProgram
  214. Wait Window Nowait [ISX terminated... TOGGLE_ISX to restart]
  215. #ELSE
  216. Wait Window nowait "ISX terminated..."
  217. #ENDIF
  218.  
  219. EndProc
  220.  
  221. *========================================================================================
  222. * Provides a generic autocomplete function. AutoComplete checks all content providers
  223. * if they have something to add to the global list and displays the list as a popup
  224. *========================================================================================
  225. Procedure AutoComplete
  226. Lparameters tcProviders, tcInvocation
  227.  
  228. *--------------------------------------------------------------------------------------
  229. * The list of providers can be limited. This speeds up program execution if one knows
  230. * from the context that only few content providers actually fit.
  231. *--------------------------------------------------------------------------------------
  232. Local lcProviders
  233. If Empty(m.tcProviders)
  234. lcProviders = "VAR,DEFINE,TABLE,OBJ"
  235. Else
  236. lcProviders = Upper(m.tcProviders)
  237. EndIf
  238.  
  239. *-----------------------------------------------------------------
  240. * Make sure, FoxTools.Fll is loaded.
  241. *-----------------------------------------------------------------
  242. If not "FOXTOOLS.FLL" $ Upper(Set("Library"))
  243. Set Library to (Home()+"FoxTools.Fll") Additive
  244. Endif
  245.  
  246. *-----------------------------------------------------------------
  247. * Get the current window and verify that it is a valid window.
  248. *-----------------------------------------------------------------
  249. Local lnWHandle
  250. lnWHandle = GetCurrentWindow()
  251. If lnWHandle == 0
  252. If not Empty(m.tcInvocation)
  253. Clear TypeAhead
  254. Keyboard "{Mouse}{Mouse}"+m.tcInvocation Plain
  255. Endif
  256. Return
  257. Endif
  258.  
  259. *-----------------------------------------------------------------
  260. * Verify that the current window is indeed an edit window.
  261. *-----------------------------------------------------------------
  262. Local lnEditSource
  263. lnEditSource = GetEditSource(m.lnWHandle)
  264. If not InList( m.lnEditSource, 1, 8, 10, 12 )
  265. If not Empty(m.tcInvocation)
  266. Clear TypeAhead
  267. Keyboard "{Mouse}{Mouse}"+m.tcInvocation Plain
  268. Endif
  269. Return
  270. EndIf
  271.  
  272. *--------------------------------------------------------------------------------------
  273. * Fill an object with details about the current context. We determine what the user
  274. * has entered so far and what's left from that Position.
  275. *--------------------------------------------------------------------------------------
  276. Local loISX
  277. loISX = CreateObject("Relation")
  278. loISX.AddProperty("nWHandle",m.lnWHandle)
  279. loISX.AddProperty("nEditSource",m.lnEditSource)
  280. loISX.AddProperty("aList[1]")
  281. loISX.AddProperty("nCount",0)
  282. loISX.AddProperty("cTextLeft",GetLineLeftFromCursor(m.lnWHandle))
  283. loISX.AddProperty("cName","")
  284. loISX.AddProperty("cEntity","")
  285. loISX.AddProperty("cInvocation",m.tcInvocation)
  286.  
  287. *--------------------------------------------------------------------------------------
  288. * Determine the part of the name that has been entered so far. This code has been
  289. * kindly provided by Louis D. Zelus.
  290. *--------------------------------------------------------------------------------------
  291. Local lcLine, lcChar
  292. If Empty(m.tcInvocation)
  293. Do While Len(m.loISX.cTextLeft) > 0
  294. lcChar = Right( m.loISX.cTextLeft, 1 )
  295. If IsAlpha(m.lcChar) or IsDigit(m.lcChar) or m.lcChar == "_"
  296. loISX.cTextLeft = Left( m.loISX.cTextLeft, Len(m.loISX.cTextLeft)-1 )
  297. loISX.cName = m.lcChar + m.loISX.cName
  298. Else
  299. Exit
  300. Endif
  301. Enddo
  302. EndIf
  303.  
  304. *--------------------------------------------------------------------------------------
  305. * Determines the name of the entity. This code is courtesy of Sietse Wijnkler.
  306. *--------------------------------------------------------------------------------------
  307. Do While Len(m.loISX.cTextLeft) > 0
  308. lcChar = Right( m.loISX.cTextLeft, 1 )
  309. If IsAlpha(m.lcChar) or IsDigit(m.lcChar) or m.lcChar == "_" or m.lcChar == "."
  310. loISX.cTextLeft = Left( m.loISX.cTextLeft, Len(m.loISX.cTextLeft)-1 )
  311. loISX.cEntity = m.lcChar + m.loISX.cEntity
  312. Else
  313. Exit
  314. Endif
  315. EndDo
  316. If Right(loISX.cEntity,1) == "."
  317. loISX.cEntity = Left( m.loISX.cEntity, Len(m.loISX.cEntity)-1 )
  318. EndIf
  319.  
  320. *--------------------------------------------------------------------------------------
  321. * This array lists all the providers
  322. *--------------------------------------------------------------------------------------
  323. Local laProvider[4,2]
  324. laProvider = ""
  325. laProvider[1,1] = "VAR"
  326. laProvider[1,2] = "CP_Variables"
  327. laProvider[2,1] = "DEFINE"
  328. laProvider[2,2] = "CP_Defines"
  329. laProvider[3,1] = "TABLE"
  330. laProvider[3,2] = "CP_Tables"
  331. laProvider[4,1] = "OBJ"
  332. laProvider[4,2] = "CP_Objects"
  333.  
  334. *--------------------------------------------------------------------------------------
  335. * Get data from each provider and merge it into the list
  336. *--------------------------------------------------------------------------------------
  337. Local laAll[1], lnAll, laRequest[1], lnRequest, lnProvider
  338. lnAll = 0
  339. For lnRequest=1 to ALines(laRequest,Chrtran(m.lcProviders,",",Chr(13)+Chr(10)),.T.)
  340. For lnProvider=1 to Alen(laProvider,1)
  341. If Upper(Alltrim(laRequest[m.lnRequest])) == laProvider[m.lnProvider,1]
  342. loISX.nCount = 0
  343. Dimension loISX.aList[1]
  344. loISX.aList = ""
  345. &laProvider[m.lnProvider,2](m.loISX)
  346. If m.loISX.nCount > 0
  347. Dimension laAll[m.lnAll+m.loISX.nCount]
  348. Acopy(m.loISX.aList,laAll,1,m.loISX.nCount, m.lnAll+1)
  349. lnAll = m.lnAll + m.loISX.nCount
  350. EndIf
  351. EndIf
  352. EndFor
  353. EndFor
  354.  
  355. *--------------------------------------------------------------------------------------
  356. * If there's anything in the list, display the popup
  357. *--------------------------------------------------------------------------------------
  358. If m.lnAll == 0
  359. If not Empty(m.tcInvocation)
  360. Clear TypeAhead
  361. Keyboard "{Mouse}{Mouse}"+m.tcInvocation Plain
  362. Endif
  363. Else
  364. If not Empty(m.tcInvocation)
  365. InsertText( m.lnWHandle, m.tcInvocation )
  366. EndIf
  367. loISX.nCount = m.lnAll
  368. Dimension loISX.aList[loISX.nCount]
  369. Acopy(laAll,loISX.aList)
  370. DisplayPopup(loISX)
  371. EndIf
  372.  
  373. EndProc
  374.  
  375. *========================================================================================
  376. * Determines all include files that fit in the current situation and adds them to the
  377. * list.
  378. *========================================================================================
  379. Procedure CP_Defines
  380. Lparameters toISX
  381.  
  382. Local loFile
  383. If Type("_VFP.ActiveProject") == "O"
  384. For each loFile in _VFP.ActiveProject.Files
  385. If Upper(JustExt(loFile.Name)) == "H"
  386. ReadDefines(m.toISX,loFile.Name)
  387. EndIf
  388. EndFor
  389. Else
  390. ReadDefines(m.toISX,Home()+"FoxPro.H")
  391. EndIf
  392.  
  393. EndProc
  394.  
  395. *========================================================================================
  396. * Adds all constants from an include file to the array.
  397. *========================================================================================
  398. Procedure ReadDefines
  399. LParameter toISX, tcFile
  400.  
  401. *--------------------------------------------------------------------------------------
  402. * File must exist.
  403. *--------------------------------------------------------------------------------------
  404. If not File(m.tcFile)
  405. Return
  406. EndIf
  407.  
  408. *--------------------------------------------------------------------------------------
  409. * To increase performance, we cache files if possible.
  410. *--------------------------------------------------------------------------------------
  411. Local laDefine[1], lnItem, lnCount
  412. If not IsInCache( "DEFINE", m.toISX, m.tcFile )
  413. If Version(4) >= "07.00"
  414. lnCount = AProcInfo(laDefine,m.tcFile)
  415. Else
  416. lnCount = X6_AProcInfo(@laDefine,m.tcFile)
  417. EndIf
  418. For lnItem=1 to m.lnCount
  419. If laDefine[m.lnItem,3] == "Define"
  420. toISX.nCount = toISX.nCount + 1
  421. Dimension toISX.aList[toISX.nCount]
  422. toISX.aList[toISX.nCount] = laDefine[m.lnItem,1]
  423. EndIf
  424. EndFor
  425. AddToCache( "DEFINE", m.toISX, m.tcFile )
  426. EndIf
  427.  
  428. EndProc
  429.  
  430. *========================================================================================
  431. * The cache is an array in _SCREEN that holds the name of the file, the time stamp, the
  432. * provider ID and the contents of the array.
  433. *========================================================================================
  434. Procedure IsInCache
  435. LParameter tcProvider, toISX, tcFile
  436.  
  437. If Type("_Screen.ISXCache[1,1]") == "U"
  438. Return .F.
  439. EndIf
  440.  
  441. Local lnLine
  442. If Version(4) >= "07.00"
  443. lnLine = Ascan( _Screen.ISXCache, m.tcFile+"?"+m.tcProvider, -1, -1, 1, 1+2+4+8 )
  444. Else
  445. Local lnCurLine
  446. lnLine = 0
  447. For lnCurLine=1 to Alen(_Screen.ISXCache,1)
  448. If Type(_Screen.ISXCache[m.lnCurLine]) == "C"
  449. If Upper(m.tcFile+"?"+m.tcProvider) == Upper(_Screen.ISXCache[m.lnCurLine])
  450. lnLine = lnCurLine
  451. Exit
  452. EndIf
  453. EndIf
  454. EndFor
  455. EndIf
  456. If m.lnLine == 0
  457. Return .F.
  458. EndIf
  459.  
  460. If Fdate(m.tcFile,1) # _Screen.ISXCache[m.lnLine,2]
  461. Return .F.
  462. EndIf
  463.  
  464. toISX.nCount = _Screen.ISXCache[m.lnLine,3]
  465. ALines( toISX.aList, _Screen.ISXCache[m.lnLine,4] )
  466.  
  467. Return .T.
  468.  
  469. *========================================================================================
  470. * Adds the current entry to the cache.
  471. *========================================================================================
  472. Procedure AddToCache
  473. LParameter tcProvider, toISX, tcFile
  474.  
  475. If Type("_Screen.ISXCache[1,1]") == "U"
  476. _Screen.AddProperty("ISXCache[1,4]")
  477. EndIf
  478.  
  479. Local lnLine
  480. If Version(4) >= "07.00"
  481. lnLine = Ascan( _Screen.ISXCache, m.tcFile+"?"+m.tcProvider, -1, -1, 1, 1+2+4+8 )
  482. Else
  483. Local lnCurLine
  484. lnLine = 0
  485. For lnCurLine=1 to Alen(_Screen.ISXCache)
  486. If Upper(m.tcFile+"?"+m.tcProvider) == Upper(_Screen.ISXCache[m.lnCurLine])
  487. lnLine = lnCurLine
  488. Exit
  489. EndIf
  490. EndFor
  491. EndIf
  492. If m.lnLine == 0
  493. lnLine = Alen(_Screen.ISXCache,1) + 1
  494. Dimension _Screen.ISXCache[m.lnLine,Alen(_Screen.ISXCache,2)]
  495. EndIf
  496.  
  497. Local lnItem
  498. _Screen.ISXCache[m.lnLine,1] = m.tcFile+"?"+m.tcProvider
  499. _Screen.ISXCache[m.lnLine,2] = Fdate(m.tcFile,1)
  500. _Screen.ISXCache[m.lnLine,3] = toISX.nCount
  501. _Screen.ISXCache[m.lnLine,4] = ""
  502. For lnItem=1 to toISX.nCount
  503. _Screen.ISXCache[m.lnLine,4] = _Screen.ISXCache[m.lnLine,4] + ;
  504. toISX.aList[m.lnItem] + Chr(13)+Chr(10)
  505. EndFor
  506.  
  507. EndProc
  508.  
  509. *====================================================================
  510. * SW: Fills an array with all PEMs for the objectname typed in
  511. * Returns the number of PEMs. The object has to exist to work
  512. *====================================================================
  513. Procedure CP_Objects
  514. Lparameters toISX
  515.  
  516. LOCAL lnVarCount
  517. If TYPE(toISX.cEntity) = [O]
  518. If Version(4) >= "07.00"
  519. If Upper(toISX.cEntity) == "_SCREEN" or Upper(toISX.cEntity) == "_VFP" ;
  520. OR Upper(toISX.cEntity) = "_VFP."
  521. Return
  522. EndIf
  523. EndIf
  524. Local laMembers[1]
  525. toISX.nCount = AMEMBERS(laMembers, Evaluate(toISX.cEntity), 1)
  526. Dimension toISX.aList[m.toISX.nCount]
  527. FOR m.lnCount = 1 TO toISX.nCount
  528. toISX.aList[m.lnCount] = PROPER(laMembers[m.lnCount,1])
  529. NEXT
  530. EndIf
  531.  
  532. EndProc
  533.  
  534. *====================================================================
  535. * SW: Fills an array with all Fields for the cursor typed in.
  536. * Returns the number of Fields. The cursor has to be open to work
  537. *====================================================================
  538. Procedure CP_Tables
  539. Lparameters toISX
  540.  
  541. LOCAL lnCount, lcName
  542. lcName = JustStem(toISX.cEntity)
  543. * November 11, 2004 Modified by Eddy Maue
  544. If Occurs(".",toISX.cEntity)==0 And !"m." == LOWER(toISX.cEntity+".") AND ;
  545. IIF(Used(m.lcName),.t.,;
  546. IIF(File(m.lcName+".dbf"),OpenTable(m.lcName),;
  547. IIF(File(m.lcName+".qpr"),ExecQuery(m.lcName),OpenView(m.lcName))))
  548.  
  549. toISX.nCount = FCOUNT(m.lcName)
  550. DIMENSION toISX.aList[toISX.nCount]
  551. FOR m.lnCount = 1 TO toISX.nCount
  552. toISX.aList[m.lnCount] = PROPER(FIELD(m.lnCount, m.lcName))
  553. NEXT
  554. ENDIF
  555.  
  556. EndProc
  557.  
  558. *====================================================================
  559. * Open the table
  560. * Eddy Maue
  561. * November 11, 2004
  562. *====================================================================
  563. Procedure OpenTable
  564. Lparameters lcName
  565. Use (m.lcName) In 0
  566. Return Used(m.lcName)
  567. ENDPROC
  568.  
  569. *====================================================================
  570. * Open a query
  571. *====================================================================
  572. * Eddy Maue
  573. * November 11, 2004
  574. *====================================================================
  575. Procedure ExecQuery
  576. Lparameters lcName
  577. Do (lcName+".qpr")
  578. Return Used(lcName)
  579. ENDPROC
  580.  
  581. *====================================================================
  582. * Open a view
  583. *====================================================================
  584. * Eddy Maue
  585. * November 11, 2004
  586. *====================================================================
  587. Procedure OpenView
  588. Lparameters lcName,lcSafety,lcConsol
  589. If Type("_vfp.ActiveProject")="U" .OR. EMPTY(DBC())
  590. Return .F.
  591. ENDIF
  592. m.lcSafety = "Set Safety "+Set("safety")
  593. Set Safety Off
  594. List Views To FILE _view.tmp NOCONSOLE
  595. If ":"+ALLTRIM(Lower(lcName))+"(" $ STRTRAN(Lower(Filetostr("_view.tmp"))," ","")
  596. Use (lcName) In 0
  597. Endif
  598. &lcSafety
  599. RETURN USED(m.lcName)
  600.  
  601. *========================================================================================
  602. * Displays a popup with all the values from taList, lets the user incrementally approach
  603. * the desired item and inserts it into the editor.
  604. *========================================================================================
  605. Procedure DisplayPopup
  606. LParameter toISX
  607.  
  608. Local loPopupForm
  609. If toISX.nCount > 0
  610. loPopupForm = CreateObject( "isxForm", toISX )
  611. If VarType(m.loPopupForm) == "O"
  612. loPopupForm.Show()
  613. Endif
  614. loPopupForm = NULL
  615. EndIf
  616. Clear Class isxForm
  617.  
  618. EndProc
  619.  
  620. *====================================================================
  621. * Determines the source of the window identified by the passed
  622. * WHandle. It returns the following values:
  623. *
  624. * -1 The window is not an edit window
  625. * 0 Command Window
  626. * 1 MODIFY COMMAND window
  627. * 2 MODIFY FILE window
  628. * 8 Menu Designer code window
  629. * 10 Method Edit Window in Class or Form Designer
  630. * 12 MODIFY PROCEDURE window
  631. *
  632. * This procedure uses _EdGetEnv() from the FoxTools.Fll to determine
  633. * the edit source. Passing an invalid handle causes an exception in
  634. * VFP 5 and VFP 3. In VFP 6 this raises an error 2028 (API function
  635. * caused an exception). Therefore we return -1 in this case, too.
  636. *====================================================================
  637. Procedure GetEditSource
  638. LParameter tnWHandle
  639.  
  640. Local laEnv[25], lnSource, lnOK, lcError
  641. lcError = On( "Error" )
  642. On Error lnOK = 0
  643. lnOK = _EdGetEnv( m.tnWHandle, @laEnv )
  644. On Error &lcError
  645. If m.lnOK == 0
  646. lnSource = -1
  647. Else
  648. lnSource = laEnv[25]
  649. Endif
  650.  
  651. Return m.lnSource
  652.  
  653. *====================================================================
  654. * Returns the WHandle of the current edit window or 0, if no edit
  655. * window is available.
  656. *====================================================================
  657. Procedure GetCurrentWindow
  658.  
  659. Local lnWindowOnTop
  660. lnWindowOnTop = _WOnTop()
  661. If m.lnWindowOnTop <= 0
  662. Return 0
  663. Endif
  664. If GetEditSource( m.lnWindowOnTop ) == -1
  665. lnWindowOnTop = 0
  666. Endif
  667.  
  668. Return m.lnWindowOnTop
  669.  
  670. *====================================================================
  671. * Returns the current cursor position in the edit window identified
  672. * by the WHandle. On error -1 is returned.
  673. *====================================================================
  674. Procedure GetFileCursorPos
  675. Lparameters tnWHandle
  676.  
  677. Local lnCursorPos
  678. lnCursorPos = _EdGetPos( m.tnWHandle )
  679.  
  680. Return m.lnCursorPos
  681.  
  682. *====================================================================
  683. * Changes the current cursor position in the edit window identified
  684. * by the WHandle.
  685. *====================================================================
  686. Procedure SetFileCursorPos
  687. LParameter tnWHandle, tnPosition
  688.  
  689. _EdSetPos( m.tnWHandle, m.tnPosition )
  690.  
  691. EndProc
  692.  
  693. *====================================================================
  694. * Returns the current line of the edit window identified by the
  695. * WHandle. The line number is zero based. On Error -1 is returned.
  696. *====================================================================
  697. Procedure GetCurrentLine
  698. LParameters tnWHandle
  699.  
  700. Local lnCursorPos, lnLineNo
  701. lnCursorPos = GetFileCursorPos( m.tnWHandle )
  702. If lnCursorPos < 0
  703. lnLineNo = -1
  704. Else
  705. lnLineNo = _EdGetLNum( m.tnWhandle, m.lnCursorPos )
  706. Endif
  707.  
  708. Return m.lnLineNo
  709.  
  710. *====================================================================
  711. * Returns the cursor position within the current line of the edit
  712. * window identified by the WHandle. The cursor position is 0 based.
  713. * On error -1 is returned.
  714. *====================================================================
  715. Procedure GetCurrentCol
  716. Lparameters tnWHandle
  717.  
  718. Local lnCursorPos, lnLineNo, lnColumn, lnLineStart
  719. lnCursorPos = GetFileCursorPos( m.tnWHandle )
  720. If m.lnCursorPos < 0
  721. Return -1
  722. Endif
  723. lnLineNo = GetCurrentLine( m.tnWHandle )
  724. If m.lnLineNo < 0
  725. Return -1
  726. Endif
  727. lnLineStart = GetLineStart( m.tnWHandle, m.lnLineNo )
  728. lnColumn = m.lnCursorPos - m.lnLineStart
  729.  
  730. Return m.lnColumn
  731.  
  732. *====================================================================
  733. * Returns the beginning of the specific line in the edit window
  734. * identified by WHandle. Returns -1 on error.
  735. *====================================================================
  736. Procedure GetLineStart
  737. LParameter tnWHandle, tnLineNo
  738.  
  739. Local lnLineStart
  740. lnLineStart = _EdGetLPos( m.tnWHandle, m.tnLineNo )
  741.  
  742. Return m.lnLineStart
  743.  
  744. *====================================================================
  745. * Returns the text of the specified line in the edit window
  746. * identified by the WHandle. A terminating carriage return is
  747. * removed. Returns an empty string on error. The line must be zero
  748. * based.
  749. *====================================================================
  750. Procedure GetLine
  751. Lparameters tnWHandle, tnLine
  752.  
  753. Local lnStartPos, lnEndPos, lcString
  754. lnStartPos = GetLineStart( m.tnWHandle, m.tnLine )
  755. lnEndPos = GetLineStart( m.tnWHandle, m.tnLine+1 )
  756. If m.lnStartPos == m.lnEndPos
  757. lcString = ""
  758. Else
  759. lnEndPos = m.lnEndPos - 1
  760. lcString = _EdGetStr( m.tnWHandle, m.lnStartPos, m.lnEndPos )
  761. lcString = Chrtran( m.lcString, Chr(13), "" )
  762. Endif
  763.  
  764. Return m.lcString
  765.  
  766. *====================================================================
  767. * Returns the text in the current line that is to the left of the
  768. * cursor in the edit window identified by the WHandle. Returns "" on
  769. * error.
  770. *====================================================================
  771. Procedure GetLineLeftFromCursor
  772. Lparameters tnWHandle
  773.  
  774. Local lnCurLine, lnCurCol, lcLine
  775. lnCurLine = GetCurrentLine( m.tnWHandle )
  776. If m.lnCurLine < 0
  777. Return ""
  778. Endif
  779. lnCurCol = GetCurrentCol( m.tnWHandle )
  780. If m.lnCurCol < 0
  781. Return ""
  782. Endif
  783. If m.lnCurCol == 0
  784. lcLine = ""
  785. Else
  786. lcLine = GetLine( m.tnWHandle, m.lnCurLine )
  787. lcLine = Left( m.lcLine, m.lnCurCol )
  788. Endif
  789.  
  790. Return m.lcLine
  791.  
  792. *====================================================================
  793. * Inserts text in the edit window identified by WHandle. The text is
  794. * stored in tcText, the position is optional. tcOptions can contains
  795. * a combination of the following values:
  796. *
  797. * R The current selection is replaced
  798. * B The cursor is positioned at the beginning of the inserted
  799. * text.
  800. * E (default) The cursor is positioned at the end of the inserted
  801. * text.
  802. * H The inserted text is highlighted.
  803. *====================================================================
  804. Procedure InsertText
  805. Lparameters tnWHandle, tcText, tnPosition, tcOptions
  806.  
  807. *-----------------------------------------------------------------
  808. * Normalize options
  809. *-----------------------------------------------------------------
  810. Local lcOptions
  811. If Vartype(m.tcOptions) == "C"
  812. lcOptions = Upper( Alltrim(m.tcOptions) )
  813. Else
  814. lcOptions = ""
  815. Endif
  816.  
  817. *-----------------------------------------------------------------
  818. * If a position is passed, Change the current cursor position
  819. * accordingly.
  820. *-----------------------------------------------------------------
  821. If Vartype(m.tnPosition) == "N"
  822. SetFileCursorPos( m.tnWHandle, m.tnPosition )
  823. Endif
  824.  
  825. *-----------------------------------------------------------------
  826. * Insert the Text at the current position. If the "R" option is
  827. * used, delete the current selection.
  828. *-----------------------------------------------------------------
  829. Local lnStartPosition, lnEndPosition
  830. If "R" $ m.lcOptions
  831. _EdDelete( m.tnWHandle )
  832. Endif
  833. lnStartPosition = GetFileCursorPos( m.tnWHandle )
  834. _EdInsert( m.tnWHandle, m.tcText, Len(m.tcText) )
  835. lnEndPosition = GetFileCursorPos( m.tnWHandle )
  836.  
  837. *-----------------------------------------------------------------
  838. * Set the cursor accordingly. "E" is the default of VFP. We don't
  839. * need any action for that.
  840. *-----------------------------------------------------------------
  841. Do Case
  842. Case "B" $ m.lcOptions
  843. SetFileCursorPos( m.tnWHandle, m.lnStartPosition )
  844. Case "H" $ m.lcOptions
  845. _EdSelect( m.tnWHandle, m.lnStartPosition, m.lnEndPosition )
  846. Endcase
  847.  
  848. EndProc
  849.  
  850. *========================================================================================
  851. * Fills an array with all variable declarations in the current procedure of the edit
  852. * window identified by the WHandle. Variable declarations are only searched backward from
  853. * the current position. Returns the number of variables.
  854. *
  855. *! 2004-10Oct-19 ChrisW
  856. * Added support for variables with non-english characters such as "�".
  857. * In VFP 9 the array limitation has been lifted.
  858. *========================================================================================
  859. Procedure CP_Variables
  860. Lparameters toISX
  861.  
  862. *--------------------------------------------------------------------------------------
  863. * Check if the current entity is a variable
  864. *--------------------------------------------------------------------------------------
  865. Local llIsVariable
  866. DO Case
  867. Case Upper(toISX.cEntity)=="M"
  868. llIsVariable = .T.
  869. Case Empty(m.toISX.cEntity)
  870. If Empty(toISX.cInvocation)
  871. llIsVariable = .T.
  872. Else
  873. llIsVariable = .F.
  874. EndIf
  875. Otherwise
  876. llIsVariable = .F.
  877. EndCase
  878. If not m.llIsVariable
  879. Return
  880. EndIf
  881.  
  882. *-----------------------------------------------------------------
  883. * Get the current line as a starting point. We start with the line
  884. * before that line.
  885. *-----------------------------------------------------------------
  886. Local lnEnd
  887. lnEnd = GetCurrentLine( toISX.nWHandle )
  888. If lnEnd <= 0
  889. Return
  890. Else
  891. lnEnd = m.lnEnd - 1
  892. Endif
  893.  
  894. *-----------------------------------------------------------------
  895. * Because GetLine() is quite slow with large program files, we
  896. * read the entire program up to the line before the current line
  897. * into an array and parse that. Since an array can only contain
  898. * up to 65000 lines, we make sure that we don't read more than
  899. * that into the laText array.
  900. *-----------------------------------------------------------------
  901. Local lnLineCount, laText[1], lnStart
  902. If m.lnEnd >= 65000 and Version(4) < "09.00"
  903. lnStart = m.lnEnd - 65000
  904. Else
  905. lnStart = 0
  906. Endif
  907. lnLineCount = AGetLines(m.toISX.nWHandle,@laText,m.lnStart,m.lnEnd)
  908.  
  909. *--------------------------------------------------------------------------------------
  910. * Parse all lines backwards for the following keywords: LOCAL,
  911. * PUBLIC, PROCEDURE, FUNCTION. We add all variables in the
  912. * LOCAL and PUBLIC lines and stop parsing when we find PROCEDURE
  913. * or FUNCTION.
  914. *--------------------------------------------------------------------------------------
  915. Local lnCurrentLine, lcLine, lnPos, lcCommand, lcValidCmds
  916. For lnCurrentLine = m.lnLineCount to 1 Step -1
  917. lcLine = NormalizeLine( laText[m.lnCurrentLine] )
  918. If Len(m.lcLine) < 4
  919. Loop
  920. EndIf
  921. If Version(4) >= "07.00"
  922. lcCommand = GetWordNum(m.lcLine,2)
  923. Else
  924. lcCommand = X6_GetWordNum(m.lcLine,2)
  925. EndIf
  926. If m.lcCommand == "="
  927. Loop
  928. EndIf
  929. If Version(4) >= "07.00"
  930. lcCommand = GetWordNum(m.lcLine,1)
  931. Else
  932. lcCommand = X6_GetWordNum(m.lcLine,1)
  933. EndIf
  934. lcValidCmds = ;
  935. "LOCAL,PUBLIC,LPARAMETERS,PARAMETERS,PRIVATE,PROCEDURE,FUNCTION,PROTECTED," + ;
  936. "HIDDEN"
  937. If not IsFoxProCommand(m.lcCommand,m.lcValidCmds)
  938. Loop
  939. EndIf
  940. lnPos = At( " ", m.lcLine )
  941. If m.lnPos == 0 or m.lnPos == Len(m.lcLine)
  942. Loop
  943. Endif
  944. lcLine = Alltrim( Substr(m.lcLine,m.lnPos) )
  945. If IsFoxProCommand(m.lcCommand,"LOCAL")
  946. If Version(4) >= "07.00"
  947. lcCommand = GetWordNum(m.lcLine,1)
  948. Else
  949. lcCommand = X6_GetWordNum(m.lcLine,1)
  950. EndIf
  951. If IsFoxProCommand(m.lcCommand,"ARRAY")
  952. lnPos = At( " ", m.lcLine )
  953. If m.lnPos == 0 or m.lnPos == Len(m.lcLine)
  954. Loop
  955. Endif
  956. lcLine = Alltrim( Substr(m.lcLine,m.lnPos) )
  957. EndIf
  958. EndIf
  959. If IsFoxProCommand( m.lcCommand, "PROCEDURE,FUNCTION,PROTECTED,HIDDEN" )
  960. lnPos = At( "(", m.lcLine )
  961. If m.lnPos == 0 or m.lnPos == Len(m.lcLine)
  962. Exit
  963. EndIf
  964. lcLine = Substr(m.lcLine,m.lnPos+1)
  965. EndIf
  966. lnCurrentLine = m.lnCurrentLine - ;
  967. CP_VariablesAdd( m.toISX, m.lcLine, m.lnCurrentLine, @laText )
  968. If IsFoxProCommand( m.lcCommand, "PROCEDURE,FUNCTION,PROTECTED,HIDDEN" )
  969. Exit
  970. Endif
  971. Endfor
  972.  
  973. EndProc
  974.  
  975. *========================================================================================
  976. *
  977. *========================================================================================
  978. Procedure CP_VariablesAdd
  979. LParameter toISX, tcLine, tnCurrentLine, taText
  980.  
  981. Local lcLine, lnLineOffset, lnCurrentVar, laDeclarations[1], lcCurrentVar, ;
  982. lnPosInVar, lcChar, lnPos
  983. lcLine = m.tcLine
  984. lnLineOffset = 0
  985.  
  986. Do While .T.
  987. lcLine = Chrtran( m.lcLine, ",", Chr(13) )
  988. For lnCurrentVar = 1 to ALines( laDeclarations, lcLine )
  989. lcCurrentVar = Alltrim( laDeclarations[m.lnCurrentVar] )
  990. If Empty( m.lcCurrentVar )
  991. Loop
  992. Endif
  993. If not IsAlpha( m.lcCurrentVar ) ;
  994. and not Left(m.lcCurrentVar,1) == "_"
  995. Loop
  996. Endif
  997. lnPos = At( " ", m.lcCurrentVar )
  998. If m.lnPos == 0
  999. lnPos = Len( m.lcCurrentVar )
  1000. Else
  1001. lnPos = m.lnPos - 1
  1002. Endif
  1003. lcCurrentVar = Left( m.lcCurrentVar, m.lnPos )
  1004. If LEFT(LOWER(m.lcCurrentVar),2)=='m.'
  1005. lcCurrentVar = SUBSTR(m.lcCurrentVar,3)
  1006. EndIf
  1007. For m.lnPosInVar = 2 to Len(m.lcCurrentVar)
  1008. lcChar = SubStr(m.lcCurrentVar,m.lnPosInVar,1)
  1009. If not (IsAlpha(m.lcChar) or IsDigit(m.lcChar) or m.lcChar="_")
  1010. lcCurrentVar = Left( m.lcCurrentVar, m.lnPosInVar-1 )
  1011. Exit
  1012. Endif
  1013. Endfor
  1014. toISX.nCount = m.toISX.nCount + 1
  1015. Dimension toISX.aList[m.toISX.nCount]
  1016. toISX.aList[m.toISX.nCount] = m.lcCurrentVar
  1017. Endfor
  1018. If Right(m.lcLine,1) # ";"
  1019. Exit
  1020. Endif
  1021. lnLineOffset = m.lnLineOffset + 1
  1022. If m.tnCurrentLine + m.lnLineOffset > Alen(taText,1)
  1023. Exit
  1024. Endif
  1025. lcLine = NormalizeLine( ;
  1026. taText[m.tnCurrentLine+m.lnLineOffset] ;
  1027. )
  1028. Enddo
  1029.  
  1030. Return m.lnLineOffset
  1031.  
  1032. *========================================================================================
  1033. * Returns .T., when the first string is a FoxPro command.
  1034. *========================================================================================
  1035. Procedure IsFoxProCommand
  1036. LParameter tcCommand, tcCommandList
  1037.  
  1038. Local laList[1], lnLine, llFound
  1039.  
  1040. llFound = .F.
  1041. For lnLine=1 to ALines(laList,Chrtran(m.tcCommandList,",",Chr(13)+Chr(10)))
  1042. If Left(Upper(laList[m.lnLine]),Len(m.tcCommand)) == Upper(m.tcCommand)
  1043. llFound = .T.
  1044. Exit
  1045. Endif
  1046. EndFor
  1047.  
  1048. Return m.llFound
  1049.  
  1050. *====================================================================
  1051. * Normalizes a line. This means: All tabs are converted to single
  1052. * blanks, leading or trailing blanks are removed. Comments starting
  1053. * with && are removed.
  1054. *====================================================================
  1055. Procedure NormalizeLine
  1056. Lparameters tcLine
  1057.  
  1058. Local lcLine, lnPos
  1059. lcLine = Chrtran( m.tcLine, Chr(9), " " )
  1060. If "&"+"&" $ m.lcLine
  1061. lnPos = At( "&"+"&", m.lcLine )
  1062. lcLine = Left( m.lcLine, m.lnPos-1 )
  1063. Endif
  1064. lcLine = Alltrim(m.lcLine)
  1065.  
  1066. Return m.lcLine
  1067.  
  1068. *====================================================================
  1069. * GetKeyLabel takes the parameters passed to the KeyPress event and
  1070. * returns the label name that can be used for KEYBOARD or ON KEY
  1071. * LABEL, etc.
  1072. *====================================================================
  1073. Procedure GetKeyLabel
  1074. LParameter tnKeyCode, tnSAC
  1075.  
  1076. Local lcLabel
  1077. Do Case
  1078. Case Between(m.tnKeyCode,33,126)
  1079. lcLabel = Chr(m.tnKeyCode)
  1080. Case Between(m.tnKeyCode,128,255)
  1081. lcLabel = Chr(m.tnKeyCode)
  1082. Case m.tnSAC == 2 and Between(m.tnKeyCode,1,26)
  1083. Do Case
  1084. Case m.tnKeyCode == 2
  1085. lcLabel = "CTRL+RIGHTARROW"
  1086. Case m.tnKeyCode == 8
  1087. lcLabel = ""
  1088. Case m.tnKeyCode == 10
  1089. lcLabel = "CTRL+ENTER"
  1090. Case m.tnKeyCode == 23
  1091. lcLabel = "CTRL+END"
  1092. Case m.tnKeyCode == 26
  1093. lcLabel = "CTRL+LEFTARROW"
  1094. Otherwise
  1095. lcLabel = "CTRL+" + Chr(m.tnKeyCode+64)
  1096. Endcase
  1097. Case m.tnSAC == 0 and m.tnKeyCode < 0
  1098. lcLabel = "F" + Alltrim(Str(Abs(m.tnKeyCode)+1))
  1099. Case m.tnSAC == 0 and m.tnKeyCode == 22
  1100. lcLabel = "INS"
  1101. Case m.tnSAC == 1 and m.tnKeyCode == 22
  1102. lcLabel = "SHIFT+INS"
  1103. Case m.tnSAC == 0 and m.tnKeyCode == 1
  1104. lcLabel = "HOME"
  1105. Case m.tnSAC == 0 and m.tnKeyCode == 7
  1106. lcLabel = "DEL"
  1107. Case m.tnSAC == 0 and m.tnKeyCode == 28
  1108. lcLabel = "F1"
  1109. Case m.tnSAC == 0 and m.tnKeyCode == 6
  1110. lcLabel = "END"
  1111. Case m.tnSAC == 0 and m.tnKeyCode == 18
  1112. lcLabel = "PGUP"
  1113. Case m.tnSAC == 0 and m.tnKeyCode == 3
  1114. lcLabel = "PGDN"
  1115. Case m.tnSAC == 0 and m.tnKeyCode == 5
  1116. lcLabel = "UPARROW"
  1117. Case m.tnSAC == 0 and m.tnKeyCode == 28
  1118. lcLabel = "F1"
  1119. Case m.tnSAC == 0 and m.tnKeyCode == 24
  1120. lcLabel = "DNARROW"
  1121. Case m.tnSAC == 0 and m.tnKeyCode == 4
  1122. lcLabel = "RIGHTARROW"
  1123. Case m.tnSAC == 0 and m.tnKeyCode == 19
  1124. lcLabel = "LEFTARROW"
  1125. Case m.tnSAC == 0 and m.tnKeyCode == 27
  1126. lcLabel = "ESC"
  1127. Case m.tnSAC == 0 and m.tnKeyCode == 13
  1128. lcLabel = "ENTER"
  1129. Case m.tnSAC == 0 and m.tnKeyCode == 127
  1130. lcLabel = "BACKSPACE"
  1131. Case m.tnSAC == 0 and m.tnKeyCode == 9
  1132. lcLabel = "TAB"
  1133. Case m.tnSAC == 0 and m.tnKeyCode == 32
  1134. lcLabel = "SPACEBAR"
  1135. Case m.tnSAC == 1 and m.tnKeyCode == 13
  1136. lcLabel = "SHIFT+ENTER"
  1137. Case m.tnSAC == 1 and m.tnKeyCode == 127
  1138. lcLabel = "SHIFT+BACKSPACE"
  1139. Case m.tnSAC == 1 and m.tnKeyCode == 15
  1140. lcLabel = "SHIFT+TAB"
  1141. Case m.tnSAC == 1 and m.tnKeyCode == 32
  1142. lcLabel = "SHIFT+SPACEBAR"
  1143. Case m.tnSAC == 2 and m.tnKeyCode == 29
  1144. lcLabel = "CTRL+HOME"
  1145. Case m.tnSAC == 2 and m.tnKeyCode == 31
  1146. lcLabel = "CTRL+PGUP"
  1147. Case m.tnSAC == 2 and m.tnKeyCode == 30
  1148. lcLabel = "CTRL+PGDN"
  1149. Case m.tnSAC == 2 and m.tnKeyCode == 128
  1150. lcLabel = "CTRL+BACKSPACE"
  1151. Case m.tnSAC == 2 and m.tnKeyCode == 32
  1152. lcLabel = "CTRL+SPACEBAR"
  1153. Otherwise
  1154. lcLabel = ""
  1155. Endcase
  1156.  
  1157. Return m.lcLabel
  1158.  
  1159. *====================================================================
  1160. * Fills an array with all lines between nStart and nEnd.
  1161. *====================================================================
  1162. Procedure AGetLines
  1163. LParameter tnWHandle, raText, tnStart, tnEnd
  1164.  
  1165. *-----------------------------------------------------------------
  1166. * Copy the text between nStart and nEnd into a string variable.
  1167. *-----------------------------------------------------------------
  1168. Local lnStartPos, lnEndPos, lcString
  1169. lnStartPos = GetLineStart( m.tnWHandle, m.tnStart )
  1170. lnEndPos = GetLineStart( m.tnWHandle, m.tnEnd+1 ) - 1
  1171. lcString = _EdGetStr( m.tnWHandle, m.lnStartPos, m.lnEndPos )
  1172.  
  1173. *-----------------------------------------------------------------
  1174. * And parse this into an array
  1175. *-----------------------------------------------------------------
  1176. Local lnCount
  1177. lnCount = ALines( raText, m.lcString )
  1178.  
  1179. Return m.lnCount
  1180.  
  1181. *====================================================================
  1182. * The FoxTools function _AGetEnv() doesn't return proper font infor-
  1183. * mation. Instead it claims that "MS Sans Serif", 8 pt. is the
  1184. * current font. This function returns font information for the speci-
  1185. * fied window by accessing the GDI.
  1186. *====================================================================
  1187. Procedure WGetFontInfo
  1188. LParameter tnWHandle, rcFontName, rnFontSize, rnStyle
  1189.  
  1190. *-----------------------------------------------------------------
  1191. * In addition to the window handle of this window we also need
  1192. * the HWND of the child window that contains the actual editor.
  1193. * The GetClientWindow() function retrieves this window handle.
  1194. *-----------------------------------------------------------------
  1195. Local lnHWND
  1196. lnHWND = GetClientWindow( m.tnWHandle )
  1197. If m.lnHWND == 0
  1198. Return .F.
  1199. Endif
  1200.  
  1201. *-----------------------------------------------------------------
  1202. * Using this HWND we can then get a Device Context.
  1203. *-----------------------------------------------------------------
  1204. Local lnHWND, lnHDC
  1205. Declare LONG GetDC in Win32API LONG
  1206. lnHDC = GetDC( m.lnHWND )
  1207. If m.lnHDC == 0
  1208. Return .F.
  1209. Endif
  1210.  
  1211. *-----------------------------------------------------------------
  1212. * With this device context we can now get an object handle to the
  1213. * currently selected font.
  1214. *-----------------------------------------------------------------
  1215. Local lnHFONT
  1216. Declare LONG GetCurrentObject in Win32API LONG, LONG
  1217. lnHFONT = GetCurrentObject( m.lnHDC, 6 ) && OBJ_FONT
  1218. If m.lnHFONT == 0
  1219. Return .F.
  1220. Endif
  1221.  
  1222. *-----------------------------------------------------------------
  1223. * The HFONT handle to the current font can be used to obtain more
  1224. * detailled information about the selected font. We need to rename
  1225. * the API function GetObject(), because it interferes with VFP's
  1226. * GETOBJECT() function
  1227. *-----------------------------------------------------------------
  1228. Local lcLogFont
  1229. Declare Integer GetObject in Win32API as GDI_GetObject ;
  1230. LONG, Integer, String@
  1231. lcLogFont = Replicate( Chr(0), 1024 )
  1232. If GDI_GetObject( m.lnHFONT, 1024, @lcLogFont ) == 0
  1233. Return .F.
  1234. Endif
  1235.  
  1236. *-----------------------------------------------------------------
  1237. * Now to extract the font information from the LOGFONT structure.
  1238. *-----------------------------------------------------------------
  1239. Local lnSize, lcName, lnStyle
  1240. lnSize = Abs( FromInt(Left(m.lcLogFont,4)) - 2^32 )
  1241. lcName = SubStr( m.lcLogFont, 29 )
  1242. lcName = Left( m.lcName, At(Chr(0),m.lcName)-1 )
  1243. lnStyle = 0
  1244. If FromInt(SubStr(m.lcLogFont,17,4)) == 700
  1245. lnStyle = m.lnStyle + 1
  1246. Endif
  1247. If FromInt(SubStr(m.lcLogFont,21,4)) # 0
  1248. lnStyle = m.lnStyle + 2
  1249. Endif
  1250.  
  1251. *-----------------------------------------------------------------
  1252. * We now have the height of the font in pixels but what we need
  1253. * are points.
  1254. *-----------------------------------------------------------------
  1255. Local lnResolution
  1256. Declare Integer GetDeviceCaps in Win32API Integer, Integer
  1257. lnResolution = GetDeviceCaps( m.lnHDC, 90 ) && LOGPIXELSY
  1258. lnSize = m.lnSize / m.lnResolution * 72
  1259. lnSize = Round( m.lnSize, 0 )
  1260.  
  1261. *-----------------------------------------------------------------
  1262. * Finally release the device context
  1263. *-----------------------------------------------------------------
  1264. Declare Integer ReleaseDC In Win32API LONG, LONG
  1265. ReleaseDC( m.lnHWND, m.lnHDC )
  1266.  
  1267. *-----------------------------------------------------------------
  1268. * And pass the values pack as parameters
  1269. *-----------------------------------------------------------------
  1270. rcFontName = m.lcName
  1271. rnFontSize = m.lnSize
  1272. rnStyle = m.lnStyle
  1273.  
  1274. Return .T.
  1275.  
  1276. *====================================================================
  1277. * The editor only works on the editor window and you can only get the
  1278. * HWND of this window using the Window Handle. For many Windows ope-
  1279. * rations, however, you need the HWND of the child window that con-
  1280. * tains the actual editor area. This function returns the HWND of
  1281. * this window. It's not that easy, because Method snippet windows
  1282. * actually have two child windows, one for the text editor and one
  1283. * with the method and object dropdown combos.
  1284. *====================================================================
  1285. Procedure GetClientWindow
  1286. LParameter tnWHandle
  1287.  
  1288. *-----------------------------------------------------------------
  1289. * Convert the Window Handle into a HWND
  1290. *-----------------------------------------------------------------
  1291. Local lnHWND
  1292. lnHWND = _WhToHWND( m.tnWHandle )
  1293.  
  1294. *-----------------------------------------------------------------
  1295. * FindWindowEx returns all child windows of a given parent window.
  1296. * We use it to find a child of the edit window that doesn't have
  1297. * another child window, because method edit windows have a second
  1298. * which we can identify since it has another child window.
  1299. *-----------------------------------------------------------------
  1300. Local lnChild
  1301. Declare Integer FindWindowEx in Win32API ;
  1302. Integer, Integer, String, String
  1303. lnChild = 0
  1304. Do While .T.
  1305. lnChild = FindWindowEx( m.lnHWND, m.lnChild, NULL, NULL )
  1306. If m.lnChild == 0
  1307. Exit
  1308. Endif
  1309. If FindWindowEx( m.lnChild, 0, NULL, NULL ) == 0
  1310. Exit
  1311. Endif
  1312. Enddo
  1313.  
  1314. Return m.lnChild
  1315.  
  1316. *====================================================================
  1317. * Returns the position of the text cursor (caret) in _SCREEN coordi-
  1318. * nates. If the window identified by the passed window handle doesn't
  1319. * have the focus, or the position can't be determined, this function
  1320. * returns .F.
  1321. *====================================================================
  1322. Procedure GetCaretPosition
  1323. LParameter tnWHandle, rnTop, rnLeft
  1324.  
  1325. *-----------------------------------------------------------------
  1326. * Check whether this window has got the focus.
  1327. *-----------------------------------------------------------------
  1328. Declare Integer GetFocus in Win32API
  1329. If GetFocus() # _WhToHWND( m.tnWHandle )
  1330. Return .F.
  1331. Endif
  1332.  
  1333. *-----------------------------------------------------------------
  1334. * Determine the cursor position. This position is relative to the
  1335. ** OK
  1336. * client area of the editing subwindow of the actual editing win-
  1337. * dow.
  1338. *-----------------------------------------------------------------
  1339. Local lnLeft, lnTop, lcPOINT
  1340. Declare Integer GetCaretPos in Win32API String@
  1341. lcPOINT = Space(8)
  1342. If GetCaretPos( @lcPOINT ) == 0
  1343. lnLeft = MCol(3)
  1344. lnTop = MRow(3)
  1345. Else
  1346. lnLeft = Asc(Left(m.lcPOINT,1))+256*Asc(SubSTr(m.lcPOINT,2,1))
  1347. lnTop = Asc(SubSTr(m.lcPOINT,5,1))+256*Asc(SubStr(m.lcPOINT,6,1))
  1348. Endif
  1349.  
  1350. *-----------------------------------------------------------------
  1351. * To convert this postion to _SCREEN coordinates, we have to
  1352. * determine the position of the client window relative to the
  1353. * desktop window and correlate this with the absolute position of
  1354. * the _SCREEN window. Hence, we need first the HWNDs of both
  1355. * windows.
  1356. *-----------------------------------------------------------------
  1357. Local lnChild, lnScreen
  1358. Declare Integer GetParent in Win32API Integer
  1359. lnChild = GetClientWindow( m.tnWHandle )
  1360. If m.lnChild == 0
  1361. Return .F.
  1362. Endif
  1363. lnScreen = GetParent( _WhToHWND(m.tnWHandle) )
  1364. If m.lnScreen == 0
  1365. Return .F.
  1366. Endif
  1367.  
  1368. *-----------------------------------------------------------------
  1369. * Now we can determine the position of both windows.
  1370. *-----------------------------------------------------------------
  1371. Local lnChildTop, lnChildLeft, lnScreenTop, lnScreenLeft, lcRect
  1372. lcRect = Replicate( Chr(0), 16 )
  1373. Declare Integer GetWindowRect in Win32API Long, String@
  1374. GetWindowRect( m.lnChild, @lcRect )
  1375. lnChildLeft = FromInt( Left(m.lcRect,4) )
  1376. lnChildTop = FromInt( SubSTr(m.lcRect,5,4) )
  1377. GetWindowRect( m.lnScreen, @lcRect )
  1378. lnScreenLeft = FromInt( Left(m.lcRect,4) )
  1379. lnScreenTop = FromInt( SubSTr(m.lcRect,5,4) )
  1380.  
  1381. *-----------------------------------------------------------------
  1382. * Now combine the position of the edit window and the cursor
  1383. * position.
  1384. *-----------------------------------------------------------------
  1385. rnLeft = m.lnLeft + m.lnChildLeft - m.lnScreenLeft
  1386. rnTop = m.lnTop + m.lnChildTop - m.lnScreenTop
  1387.  
  1388. EndProc
  1389.  
  1390. Procedure FromInt
  1391. Parameter tcString
  1392. Private nValue, nT
  1393. nValue =0
  1394. For nT = 1 to Len(tcString)
  1395. nValue = nValue + Asc(SubStr(tcString,nT,1))*256^(nT-1)
  1396. Endfor
  1397. Return nValue
  1398.  
  1399. *====================================================================
  1400. * The following class displays a popup window at the current cursor
  1401. * position and lets the user continue to type.
  1402. *
  1403. * The characters a-z, A-Z, 0-9 and _ are inserted into the active
  1404. * edit window as the user types. The previous position is saved in
  1405. * order to restore the text if necessary.
  1406. *
  1407. * ESC terminates the popup and doesn't change the text.
  1408. *
  1409. * TAB inserts the current selection and terminates the popup.
  1410. *
  1411. * SPACEBAR inserts the current selection, adds a blank and terminates
  1412. * the popup.
  1413. *
  1414. * Any other key terminates the popup and is repeated so it is handled
  1415. * properly by VFP. If the user enters the first character that
  1416. * doesn't match an item in the list, or entered a full item where
  1417. * none exists that has the same name, but additional characters, the
  1418. * list is terminated as well.
  1419. *
  1420. *====================================================================
  1421. Define CLASS isxForm as Form
  1422.  
  1423. AlwaysOnTop = .T.
  1424. WindowType = 1
  1425. TitleBar = 0
  1426. BorderStyle = 0
  1427.  
  1428. nWHandle = 0
  1429. nCurrentPos = 0
  1430. cSearchString = ""
  1431. cVarString = ""
  1432. Dimension aItems[1,2]
  1433. lScrolled = .F.
  1434. *Mike Yearwood - these support reducing screen caption flicker
  1435. cScreenCaption = ""
  1436. cWindowCaption = ""
  1437. lMaximized = .F.
  1438.  
  1439. Add Object isxList as Listbox with ;
  1440. ColumnCount = 2, ;
  1441. ColumnLines = .F., ;
  1442. IncrementalSearch = .F.
  1443.  
  1444. PROCEDURE Load
  1445. this.lMaximized = wmaximum()
  1446. IF THIS.lMaximized
  1447. THIS.cWindowCaption = LOWER(WTITLE())
  1448. THIS.cScreenCaption = _screen.Caption
  1449. ENDIF
  1450. RETURN DODEFAULT()
  1451. ENDPROC
  1452.  
  1453. PROCEDURE Show
  1454. *====================================================================
  1455. * Mike Yearwood
  1456. * When the edit window is maximized, the screen caption reads
  1457. * currentedit.prg * - current vfp system window caption
  1458. * When this window goes active, the screen caption changes
  1459. * which causes a flicker. To stop that flicker, set the screen
  1460. * caption to what it was before.
  1461. *====================================================================
  1462.  
  1463. IF THIS.lMaximized
  1464. _Screen.Caption = this.cWindowCaption + " * - " + this.cScreenCaption
  1465. ENDIF
  1466. ENDPROC
  1467.  
  1468. PROCEDURE Destroy
  1469. *Mike Yearwood
  1470. *Prevent screen caption flicker.
  1471. IF THIS.lMaximized
  1472. _Screen.Caption = this.cScreenCaption
  1473. ENDIF
  1474. ENDPROC
  1475.  
  1476. *====================================================================
  1477. * When the form is initialized, we have to determine its position
  1478. * and get a handle to the current edit window. Pass an array to this
  1479. * form that contains all possible values the user can enter.
  1480. *====================================================================
  1481. Procedure Init
  1482. LParameter toISX
  1483. With This
  1484.  
  1485. *-----------------------------------------------------------------
  1486. * Get the handle for the current window.
  1487. *-----------------------------------------------------------------
  1488. .nWHandle = toISX.nWHandle
  1489. .nCurrentPos = GetFileCursorPos( .nWHandle )
  1490.  
  1491. *-----------------------------------------------------------------
  1492. * Copy the array and sort it case-insensitive
  1493. *-----------------------------------------------------------------
  1494. Local laValues[1], lnValue
  1495. If Version(4) >= "07.00"
  1496. Asort( toISX.aList, -1, -1, 0, 1 )
  1497. Else
  1498. Dimension laValues[toISX.nCount,2]
  1499. For lnValue = 1 to toISX.nCount
  1500. laValues[m.lnValue,1] = Upper(toISX.aList[m.lnValue])
  1501. laValues[m.lnValue,2] = m.lnValue
  1502. EndFor
  1503. Asort( laValues, 1 )
  1504. EndIf
  1505.  
  1506. *--------------------------------------------------------------------------------------
  1507. * Fill the listbox with all possible values.
  1508. *--------------------------------------------------------------------------------------
  1509. Local lcValue, lnWidth, lnMaxWidth, lnValue, lcVarString, lnAvgCharWidth
  1510. lnMaxWidth = 0
  1511. lcVarString = ""
  1512. Dimension .aItems[toISX.nCount,2]
  1513. lnAvgCharWidth = Fontmetric(6,.isxList.FontName,.isxList.FontSize)
  1514. For lnValue = 1 to toISX.nCount
  1515. If Version(4) >= "07.00"
  1516. lcValue = toISX.aList[m.lnValue]
  1517. Else
  1518. lcValue = toISX.aList[laValues[m.lnValue,2]]
  1519. EndIf
  1520. .aItems[m.lnValue,1] = Upper(m.lcValue)
  1521. .aItems[m.lnValue,2] = m.lcValue
  1522. lcVarString = m.lcVarString + ":" + Padr(Upper(m.lcValue),128)
  1523. lnWidth = Txtwidth(m.lcValue,.isxList.FontName,.isxList.FontSize) * m.lnAvgCharWidth
  1524. lnMaxWidth = Max( m.lnMaxWidth, m.lnWidth )
  1525. EndFor
  1526. .cVarString = m.lcVarString
  1527. lnMaxWidth = m.lnMaxWidth + 30
  1528. With .isxList
  1529. .ColumnWidths = "0," + Alltrim(Str(m.lnMaxWidth))
  1530. .RowSource = "Thisform.aItems"
  1531. .RowSourceType = 5
  1532. .Requery()
  1533. .Move( 0, 0, m.lnMaxWidth, 110 )
  1534. If .ListCount < 6
  1535. .Height = .ListCount*16 + 14
  1536. Endif
  1537. EndWith
  1538. .Width = m.lnMaxWidth
  1539. .Height = .isxList.Height
  1540.  
  1541. *-----------------------------------------------------------------
  1542. * The original version of the following few code blocks has been
  1543. * kindly provided by Louis D. Zelus. I've modified it to match the
  1544. * rest of the code here. The purpose is to simulate a behavior
  1545. * in VB. If the variable is inserted via ALT+I, everything already
  1546. * typed is used to position the list and if the already entered
  1547. * parts are sufficient to uniquely identify the variablem it's
  1548. * inserted without displaying the popup at all. All blocks based
  1549. * on his code start with LDZ.
  1550. *-----------------------------------------------------------------
  1551.  
  1552. *-----------------------------------------------------------------
  1553. * LDZ: If a variable name has been entered, we highlight it in the
  1554. * edit window.
  1555. *-----------------------------------------------------------------
  1556. Local lnStartPos, lnEndPos, lcInput
  1557. lcInput = toISX.cName
  1558. If Len(m.lcInput) > 0
  1559. lnEndPos = GetFileCursorPos( .nWHandle )
  1560. lnStartPos = m.lnEndPos - Len(m.lcInput)
  1561. _EdSelect( .nWHandle, m.lnStartPos, m.lnEndPos )
  1562. Endif
  1563.  
  1564. *-----------------------------------------------------------------
  1565. * LDZ: Try to find this variable name in the list of variables we
  1566. * assembled above. If we find it, we select this entry and save
  1567. * what has been entered so far.
  1568. *-----------------------------------------------------------------
  1569. Local lnIndex
  1570. If Len(m.lcInput) > 0
  1571. lnIndex = At( ":"+Upper(m.lcInput), .cVarString )
  1572. If m.lnIndex == 0
  1573. .isxlist.ListIndex = 0
  1574. Else
  1575. .isxlist.ListIndex = (m.lnIndex/129) + 1
  1576. Endif
  1577. .cSearchString = m.lcInput
  1578. Endif
  1579.  
  1580. *-----------------------------------------------------------------
  1581. * LDZ: If there's no second instance of this start, accept it
  1582. * immediately without displaying the popup. The full variable name
  1583. * is inserted with the proper case at the current position
  1584. * replacing the selection.
  1585. *-----------------------------------------------------------------
  1586. If Len(m.lcInput) > 0
  1587. If At( ":"+Upper(m.lcInput), .cVarString, 2 ) == 0 ;
  1588. and not m.lnIndex == 0
  1589. InsertText( .nWHandle, "", , "R" )
  1590. InsertText( .nWHandle, .isxList.List[.isxList.ListIndex,2] )
  1591. Return .F.
  1592. Endif
  1593. Endif
  1594.  
  1595. *-----------------------------------------------------------------
  1596. * Determine the cursor position in _SCREEN coordinates
  1597. *-----------------------------------------------------------------
  1598. Local lnLeft, lnTop
  1599. If not GetCaretPosition( .nWHandle, @lnTop, @lnLeft )
  1600. Return .F.
  1601. Endif
  1602.  
  1603. *-----------------------------------------------------------------
  1604. * As we position the popup BELOW the current line, we need to
  1605. * know the height of this line in pixels.
  1606. *-----------------------------------------------------------------
  1607. Local lnLineHeight, lnAvgCharWidth, lcFontName, lnFontSize
  1608. If not WGetFontInfo( .nWHAndle, @lcFontName, @lnFontSize )
  1609. Return .F.
  1610. Endif
  1611. lnLineHeight = FontMetric( 1, m.lcFontName, m.lnFontSize )
  1612. lnAvgCharWidth = FontMetric(6,m.lcFontName,m.lnFontSize)
  1613.  
  1614. *-----------------------------------------------------------------
  1615. * We make sure that the popup doesn't move below the VFP window to
  1616. * keep it visible all the time. If it doesn't fit into the area
  1617. * below the cursor, we move it upwards.
  1618. *-----------------------------------------------------------------
  1619. If m.lnTop + .Height + m.lnLineHeight > _Screen.Height
  1620. lnTop = m.lnTop - .Height
  1621. Else
  1622. lnTop = m.lnTop + m.lnLineHeight
  1623. Endif
  1624. .Top = m.lnTop
  1625.  
  1626. *------------------------------------------------------------------
  1627. * As for the height of the VFP window, we do the same for the
  1628. * width. If the popup won't fit into the VFP _Screen, we flip
  1629. * it horizontally.
  1630. *------------------------------------------------------------------
  1631. If m.lnLeft + .Width + lnAvgCharWidth > _Screen.Width
  1632. lnLeft = m.lnLeft - .Width
  1633. Else
  1634. lnLeft = m.lnLeft + lnAvgCharWidth
  1635. EndIf
  1636. .Left = m.lnLeft
  1637. Endwith
  1638. EndProc
  1639.  
  1640. *========================================================================================
  1641. * If we don't hide the popup before releasing it, the focus might not go back to the
  1642. * edit window. This happens when we have a Data Session window docked on one side and
  1643. * a code editing window maximized. In this case the focus switches to the datasession
  1644. * window and Aliases listbox disappears.
  1645. *========================================================================================
  1646. Procedure Release
  1647. This.Hide()
  1648. EndProc
  1649.  
  1650. Procedure isxList.KeyPress
  1651. LParameter tnKeyCode, tnSAC
  1652. With This
  1653.  
  1654. *-----------------------------------------------------------------
  1655. * If the Up or Down Arrow has been pressed, we do nothing, but
  1656. * remember that the user scrolled in the list, because this acti-
  1657. * vates the enter key.
  1658. *-----------------------------------------------------------------
  1659. Local llScrolled
  1660. If m.tnSAC == 0 and InList( m.tnKeyCode, 5, 24 )
  1661. .Parent.lScrolled = .T.
  1662. Return
  1663. Endif
  1664. llScrolled = .Parent.lScrolled
  1665. .Parent.lScrolled = .F.
  1666.  
  1667. *-----------------------------------------------------------------
  1668. * Determines whether a name qualifier has been entered.
  1669. *-----------------------------------------------------------------
  1670. Local llQualifier
  1671. llQualifier = .F.
  1672. If m.tnSAC == 0 and Between(m.tnKeyCode,Asc("a"),Asc("z"))
  1673. llQualifier = .T.
  1674. Endif
  1675. If m.tnSAC == 1 and Between(m.tnKeyCode,Asc("A"),Asc("Z"))
  1676. llQualifier = .T.
  1677. Endif
  1678. If m.tnSAC == 0 and Between(m.tnKeyCode,Asc("0"),Asc("9"))
  1679. llQualifier = .T.
  1680. Endif
  1681. If m.tnSAC == 1 and m.tnKeyCode == Asc("_")
  1682. llQualifier = .T.
  1683. Endif
  1684.  
  1685. *-----------------------------------------------------------------
  1686. * If a qualifier has been entered, we insert the character into
  1687. * the current edit window. We also perform an incremental search
  1688. * on the Text being inserted.
  1689. *-----------------------------------------------------------------
  1690. Local lcSearch, lnIndex
  1691. If m.llQualifier
  1692. lcSearch = .Parent.cSearchString + Chr(m.tnKeyCode)
  1693. Endif
  1694.  
  1695. *-----------------------------------------------------------------
  1696. * BACKSPACE deletes the last character.
  1697. *-----------------------------------------------------------------
  1698. If m.tnSAC == 0 and m.tnKeyCode == 127
  1699. If Len(.Parent.cSearchString) > 0
  1700. lcSearch = .Parent.cSearchString
  1701. lcSearch = Left( m.lcSearch, Len(m.lcSearch)-1 )
  1702. llQualifier = .T.
  1703. Endif
  1704. Endif
  1705.  
  1706. *-----------------------------------------------------------------
  1707. * Now that we handled BACKSPACE, we can update the variable name
  1708. * in the edit window.
  1709. *-----------------------------------------------------------------
  1710. If m.llQualifier
  1711. InsertText( .Parent.nWHandle, m.lcSearch, , "RH" )
  1712. lnIndex = At( ":"+Upper(m.lcSearch), .Parent.cVarString )
  1713. If m.lnIndex == 0
  1714. .ListIndex = 0
  1715. Else
  1716. .ListIndex = (m.lnIndex/129) + 1
  1717. Endif
  1718. .Parent.cSearchString = m.lcSearch
  1719. NoDefault
  1720. Return
  1721. Endif
  1722.  
  1723. *-----------------------------------------------------------------
  1724. * The following flags determine how to procede.
  1725. *-----------------------------------------------------------------
  1726. Local lcTextToInsert, llResendKey, llClearInput
  1727. lcTextToInsert = ""
  1728. llResendKey = .T.
  1729. llClearInput = .F.
  1730. Do Case
  1731.  
  1732. *-----------------------------------------------------------------
  1733. * If TAB has been pressed, insert the current selection and
  1734. * release the popup
  1735. *-----------------------------------------------------------------
  1736. Case m.tnSAC == 0 and m.tnKeyCode == 9 and .ListIndex > 0
  1737. lcTextToInsert = .List[.ListIndex,2]
  1738. llResendKey = .F.
  1739. llClearInput = .T.
  1740.  
  1741. *-----------------------------------------------------------------
  1742. * If ENTER has been pressed after the user made a selection with
  1743. * the arrow keys, we insert the current selection and release the
  1744. * popup, because after scrolling the user has the feeling of using
  1745. * a plain listbox where enter performs a selection.
  1746. *-----------------------------------------------------------------
  1747. Case m.tnSAC == 0 ;
  1748. and m.tnKeyCode == 13 ;
  1749. and .ListIndex > 0 ;
  1750. and m.llScrolled
  1751. lcTextToInsert = .List[.ListIndex,2]
  1752. llResendKey = .F.
  1753. llClearInput = .T.
  1754.  
  1755. *-----------------------------------------------------------------
  1756. * Several keys insert the current selection plus the typed
  1757. * character and release the popup. These are usually keys that
  1758. * directly follow a variable name.
  1759. *-----------------------------------------------------------------
  1760. Case InList(m.tnKeyCode, ;
  1761. Asc(" "), Asc(")"), Asc("["), Asc("."), Asc("="), ;
  1762. Asc("+"), Asc("-"), Asc("*"), Asc("/"), Asc("%"), ;
  1763. Asc(","), Asc("]") ;
  1764. ) and .ListIndex > 0
  1765. lcTextToInsert = .List[.ListIndex,2]
  1766. llClearInput = .T.
  1767.  
  1768. *-----------------------------------------------------------------
  1769. * If ESC has been pressed, the text is unselected.
  1770. *-----------------------------------------------------------------
  1771. Case m.tnSAC == 0 and m.tnKeyCode == 27
  1772. llResendKey = .F.
  1773.  
  1774. *-----------------------------------------------------------------
  1775. * terminate the popup for any other key and leave the text.
  1776. *-----------------------------------------------------------------
  1777. Otherwise
  1778. Endcase
  1779.  
  1780. *-----------------------------------------------------------------
  1781. * If the currently entered Text should be deleted, insert an empty
  1782. * string using the replace option. Insert text afterwards.
  1783. *-----------------------------------------------------------------
  1784. If m.llClearInput
  1785. InsertText( .Parent.nWHandle, "", , "R" )
  1786. Else
  1787. SetFileCursorPos( ;
  1788. .Parent.nWHandle, ;
  1789. .Parent.nCurrentPos + Len(.Parent.cSearchString) ;
  1790. )
  1791. Endif
  1792. If not Empty( m.lcTextToInsert )
  1793. InsertText( .Parent.nWHandle, m.lcTextToInsert )
  1794. Endif
  1795.  
  1796. *-----------------------------------------------------------------
  1797. * Close the form.
  1798. *-----------------------------------------------------------------
  1799. NoDefault
  1800. Thisform.Release()
  1801.  
  1802. *-----------------------------------------------------------------
  1803. * And repeat the keystroke if necessary
  1804. *-----------------------------------------------------------------
  1805. Local lcKey
  1806. If m.llResendKey
  1807. lcKey = GetKeyLabel( m.tnKeyCode, m.tnSAC )
  1808. If not Empty(m.lcKey)
  1809. Clear TypeAhead
  1810. If Len(m.lcKey) == 1
  1811. Keyboard m.lcKey
  1812. Else
  1813. Keyboard "{"+m.lcKey+"}"
  1814. Endif
  1815. Endif
  1816. Endif
  1817.  
  1818. Endwith
  1819. EndProc
  1820.  
  1821. *====================================================================
  1822. * Double-clicking is the same as TAB.
  1823. *====================================================================
  1824. Procedure isxList.DblClick
  1825.  
  1826. Clear TypeAhead
  1827. Keyboard "{Tab}" Plain
  1828.  
  1829. EndProc
  1830.  
  1831. EndDefine
  1832.  
  1833. *========================================================================================
  1834. * VFP 6: Returns a specific word in a string
  1835. *========================================================================================
  1836. Function X6_GetWordNum
  1837. LParameter tcString, tnWord, tcDelimiter
  1838.  
  1839. Local lcString, lcDelimiter, lnWord, laWords[1], lnFound, lcWord
  1840.  
  1841. If Vartype(m.tcDelimiter) == "C"
  1842. lcDelimiter = m.tcDelimiter
  1843. Else
  1844. lcDelimiter = Chr(9)+Chr(32)
  1845. EndIf
  1846. lcString = Chrtran(m.tcString,m.lcDelimiter,Replicate(Chr(13),Len(m.lcDelimiter)))
  1847. lnFound = 0
  1848. lcWord = ""
  1849. For lnWord = 1 to ALines(laWords,m.lcString)
  1850. If not Empty(laWords[m.lnWord])
  1851. lnFound = lnFound + 1
  1852. If m.lnFound == m.tnWord
  1853. lcWord = laWords[m.lnWord]
  1854. Exit
  1855. EndIf
  1856. EndIf
  1857. EndFor
  1858.  
  1859. Return m.lcWord
  1860.  
  1861. *========================================================================================
  1862. * VFP 6: Returns a list of all defines
  1863. *========================================================================================
  1864. Procedure X6_AProcInfo
  1865. LParameter taArray, tcFile
  1866.  
  1867. Local laLines[1], lnLine, lnFound
  1868.  
  1869. lnFound = 0
  1870. For lnLine = 1 to ALines(laLines,FileToStr(m.tcFile))
  1871. If Upper(X6_GetWordNum(laLines[m.lnLine],1)) == "#DEFINE"
  1872. lnFound = lnFound + 1
  1873. Dimension taArray[m.lnFound,3]
  1874. taArray[m.lnFound,1] = X6_GetWordNum(laLines[m.lnLine],2)
  1875. taArray[m.lnFound,3] = "Define"
  1876. EndIf
  1877. EndFor
  1878.  
  1879. Return m.lnFound

vfp 智能感知拓展应用的更多相关文章

  1. Visual studio智能感知挡住了当前代码输入行

    AssistX->Listboxes->Enable Visual Assist completion, suggestion and member list in .. 如果勾选了该项就 ...

  2. tsd-提升IDE对JavaScript智能感知的能力

    在编写前端JavaScript代码时,最痛苦的莫过于代码的智能感知(Intelli Sense). 追其根源,是因为JavaScript是一门弱类型的动态语言.对于弱类型的动态语言来说,智能感知就是I ...

  3. SSMS 2008R2没有智能感知方法解决

    有时SSMS会莫明奇妙的没有了智能感知(前一天还是有的, 第2天就没有了) 在网上查到有如下原因: 1. 服务器上有Offline的DB 解决方案: 将Offline的DB删掉或者设成online即可 ...

  4. Visual Studio中Js使用智能感知

    使用了第三方的JS库或框架,在VS中编写JS代码,发现真是个悲剧,完全只能手打,智能感知没了,这不符合VS的一贯做风只要在写代码的JS文件加上以下代码,就可以有智能感知了 ///<referen ...

  5. WiEngine+Eclipse+CDT+Sequoyah实现c++编程智能感知提示

    经过一段时间的摸索,我初步肯定自己基于WiEngine平台和C++开发跨Android/iPhone游戏的最佳(至少目前)环境为: Eclipse+CDT+Sequoyah 第一,JAVA代码调试技术 ...

  6. Red Gate系列之三 SQL Server 开发利器 SQL Prompt 5.3.4.1 Edition T-SQL智能感知分析器 完全破解+使用教程

    原文:Red Gate系列之三 SQL Server 开发利器 SQL Prompt 5.3.4.1 Edition T-SQL智能感知分析器 完全破解+使用教程 Red Gate系列之三 SQL S ...

  7. RFID智能感知摄像机推进智慧城市建设步伐

    随着智慧城市建设步伐的大力推进,各地的智慧城市建设取得了卓有成效的成果.物联网工程正在如火如荼地进行,顺应智慧城市物联网的发展大趋势,建设城市级的视频感知网,涉及治安.交通.教育等多方面综合传感应用, ...

  8. WPF中实现类智能感知

    首先要做的事情就是定义一个popup来显示我们需要展示的东西 <Popup x:Name=" StaysOpen="False" Placement="B ...

  9. 为 NativeScript 项目添加 iOS / Android 平台 API 的智能感知

    使用 NativeScript ,我们可以很容易的调用平台的原生 API,在开发过程中,我们可以添加这些 API 的 d.ts 文件来提供智能感知,帮助我们更方便的构建媲美原生的 APP. 首先通过 ...

随机推荐

  1. JBoss-7.1.1 http访问端口修改

    修改http服务端口 找到 jboss-as-7.1.1.Final/standalone/configuration/standalone.xml文件,找到第298行,如下图: 如果我们想改成80端 ...

  2. Python自动化测试 (九)urllib2 发送HTTP Request

    urllib2 是Python自带的标准模块, 用来发送HTTP Request的.  类似于 .NET中的,  HttpWebRequest类 urllib2 的优点 Python urllib2 ...

  3. 如何更换centos6源

    1.wget http://mirrors.163.com/.help/CentOS6-Base-163.repo 2.根据教程:http://mirrors.163.com/.help/centos ...

  4. 一生伏首拜阳明------<明朝那些事儿>

    一生伏首拜阳明. 王守仁,字伯安,别号阳明. 成化八年(1472),王守仁出生在浙江余姚,大凡成大事者往往出身贫寒,小小年纪就要上山砍柴,下海捞鱼,家里还有几个生病的亲属,每日以泪洗面.这差不多也是惯 ...

  5. makefile 学习网站

    http://blog.csdn.net/ruglcc/article/details/7814546/#t30

  6. mysql数据库使用

    C#操作Mysql数据库的存储过程,网址 DATEDIFF() 函数返回两个日期之间的天数. 语法 DATEDIFF(date1,date2) date1 和 date2 参数是合法的日期或日期/时间 ...

  7. jsp页面验证码(完整实例)

    项目结构如下,MyEclipse中新建一个Web Project,取名servlet 1.src下new一个servlet类 package com.servlet; import java.awt. ...

  8. mysql使用

    1.以查询结果建表 create table newTableName select column1 [newName1] [, column2 [newName2], .. , columnn [n ...

  9. jsp学习之基于mvc学生管理系统的编写

    mvc开发模式:分别是 model层 view层 Control层 在学生管理系统中,model层有学生实体类,数据访问的dao层,view层主要是用于显示信息的界面,Control层主要是servl ...

  10. android学习之线性布局

    效图如下 移通152余继彪 该布局使用了线性布局完成 父布局为线性布局,黄色和灰色部分为水平的线性布局,剩余50%部分为水平线性布局,该布局中包含了两个垂直的线性布局分别占了三分之1和三分之二