The MASM Forum

Miscellaneous => Miscellaneous Projects => Topic started by: mywan on July 18, 2012, 07:31:02 AM

Title: Contextual help project
Post by: mywan on July 18, 2012, 07:31:02 AM
I would also like to inquire about the copyright issues if I used some of the help file source code contained in \masm32\help\*.chm to create a more friendly help file structure, as described below. I also think a project like this is worthy of attention in the MASM SDK release.

The ASM/MASM documentation contains a lot of information, yet the process of finding any particular material can be laborious. Even if it wasn't spread around multiple help files they are not searchable. Neither are these series of help files very friendly to embedding in context sensitive help. Such as placing the cursor over "lfcnt" and pressing F1 to go directly to "hh.exe C:\masm32\help\masmlib.chm::/lfcnt.htm". Masmlib.chm tends to be one of the more friendly for this feature, but remains difficult to search and lacks cross referenced linking. Especially to other help files.

I would like to recreate most of these help files in a single well cross linked help system to make finding very specific information as simple as a single keystroke. Various index pages could then group these pages in logical content so that what was previously included as separate help files are categories in the content index. There wouldn't even be a limit on the number of index pages, or even index of index pages. In an uncompiled form it could also be hosted on the web and retain the same functionality for integration into text editors. The forum code tags could also auto-link these keywords to specific mnemonic help files.

Personally a well designed help system would save me more than 90% of my time on the learning curve, and greatly reduce development time forever. This means that every keyword, regardless of how basic or seemingly inane, should have its own page as <keyword>.htm, or <keyword>.chm in compiled form. These can also be back linked to any index page(s) that include them. Also any keywords mentioned in those pages should be crosslinked. This could be done wiki style and simply wrap the keywords in [[[<keyword>]]], such that a macro could expand them into links. It is after all the arcane-ish mnemonics of asm that makes it such an arcane beast for most people. This capacity would massively reduce the difficulties these mnemonics create for people.

The main idea is to provide full and complete integration of a singular MASM help file system into text editors, forum content, web searches, etc. How many others here would be interested in a help system of this nature? I think it would also generate a lot of new interest in the language itself.
Title: Re: Contextual help project
Post by: jj2007 on July 18, 2012, 08:25:52 AM
Here is one way to do it:
- decompile the whole stuff
- load the contents into an array
- do a full text search
- show a list of matches
- let the user click on it
- display the HTML

My first attempt shows that speedwise it can be done, here for MasmLib.chm:

31 ms for loading 201 files
Type a search term (Esc+Enter to exit): bitmap
Found in \masm32\help\MasmLib\BitmapFromFile.htm
Found in \masm32\help\MasmLib\BitmapFromMemory.htm
Found in \masm32\help\MasmLib\BitmapFromResource.htm
Found in \masm32\help\MasmLib\BmpButton.htm
Found in \masm32\help\MasmLib\DisplayBmp.htm
Found in \masm32\help\MasmLib\Image Functions.htm
Found in \masm32\help\MasmLib\Notes On Encryption.htm
Found in \masm32\help\MasmLib\VerticalTile.htm
Search took 1 ms

No problem to do that simultaneously for all 10 CHM files, provided there are no name conflicts. Of course, a fulltext search in the whole package would then cost 10 milliseconds instead of one ;-)

Source & exe attached.
Title: Re: Contextual help project
Post by: mywan on July 18, 2012, 09:05:35 AM
Every one of those files found to contain "bitmap" are contained in one help file: masmlib.chm. I use a search app to search in files to find references in the compiled chm. To retrieve a page id I can directly access requires a more specialized search though, and the chm files don't even have a search function of their own. So decompiling is really the only way to get direct linking access to a found reference, because otherwise you don't know where in the help file to find the reference.

I think the entire help file system needs a complete rewrite. That would start with a huge list of individual pages and a template to provide a uniform layout.

Edit: Just read your source and realized masmlib.chm was the only one you decompiled. Even without decompiling these strings can be found as plain text. Though it still leaves the main problem unresolved.
Title: Re: Contextual help project
Post by: hutch-- on July 18, 2012, 10:29:18 AM
I don't like to rain on the parade but there is very good reason why the entire MASM32 SDK is a copyright work and will remain that way.

The help files are split up into categories so that the user does not have to climb through a mountain of other stuff to find what they need.

Try and find anything SDK in the current batch of Microsoft help files and you will well understand why I don't want a massive single file for all of the different forms of data.
Title: Re: Contextual help project
Post by: mywan on July 18, 2012, 12:56:09 PM
I'll respect the copyrights :t It was pretty much to be expected anyway.
I suppose I can still refer to them by name. I am still going to develop my own context sensitive help system simply because I really can't be very productive otherwise. I'm literally spending several hours a day trying to dig out information that should be milliseconds away. Not everything there belongs in context sensitive help anyway.

Perhaps I will simply create a redirector a text editor can use to retrieve the proper command line to get the proper chm page, such as:
hh.exe "C:\masm32\help\hlhelp.chm::/Using%20.REPEAT%20Syntax.htm"
My Drawer program I intend to rewrite in asm is capable of this, if configured right, by default, and requires the user to actually posses the help files from the SDK. I can then include some html, perhaps compiled, files for keywords that are not included and part of the asm core mnemonics.
Title: Re: Contextual help project
Post by: jj2007 on July 18, 2012, 03:07:58 PM
Every one of those files found to contain "bitmap" are contained in one help file: masmlib.chm.
...
Edit: Just read your source and realized masmlib.chm was the only one you decompiled. Even without decompiling these strings can be found as plain text. Though it still leaves the main problem unresolved.

@Even without decompiling these strings can be found as plain text
Yes indeed:
/bin2hex.htm..‚..:./BinSearch.htm...:.c./BitmapFromFile.htm....6./BitmapFromMemory.htm....../BitmapFromResource.htm..../BmpButton.htm.../Boyer Moore Algorithms.htm..›../BrowseForFolder.htm...

Now go and find .gif, and you will realise why splitting is the better alternative.
For the time being, I just decompiled one of the chm files, but using all of them is just a question of three lines more or so.

Provided Hutch does not ban us from using the help folder as input to a software that displays them exactly as they would be displayed by the Windows HtmpHelp software :biggrin:
Title: Re: Contextual help project
Post by: mywan on July 18, 2012, 04:31:00 PM
No banning please, at least not without a warning :greenclp: I promise to be very respectful and law abiding.

I've started down another road. I got a fresh copy of SciTE and started an asm configuration to include a copy of my Drawer program with. To avoid a bloated ini file I'm going to slightly modify a separate slimmer copy of my drawer program to offer a drawer of help option when F1 is pressed. Probably move my compile options menu there to. One of the options will be labeled "Help <keyword>" if one is available in the config file. This will simply open the existing chm needed to get help on that keyword. Requires a dictionary lookup for the proper locations though, hence the concerns about bloat in my windows version which already has a complete dictionary of filetypes. Other options can include local or internet resources, your own separate html or chm files, and including search strings to "Google <keyword>". Perhaps even a "find in file" to search which help files contain certain keywords. It all just depends on what you put in the config file.

Decompiling would certainly help make finding many help entries easier. However, I can paste text into the Drawer's configuration simply by right clicking the GUI. So by programmatically modifying the pasted string a bit I can just right click each page in the chm, select properties, copy the location string and paste it directly in the GUI. From there I get a prompt to accept the keyword the Drawer guessed at or modify it before accepting the entry. "bin2hex" stripped from "/bin2hex.htm" is a valid keyword, but "Using REPEAT Syntax" from "hlhelp.chm::/Using%20.REPEAT%20Syntax.htm" wouldn't be.

Anyway, that's the approach I have decided on.
Title: Re: Contextual help project
Post by: jj2007 on July 25, 2012, 02:51:26 AM
I made some little tests, it seems to work most of the time but the GUI needs to be improved.
Attached version 0.9; version 1.0 should have the option to send a WM_COPYDATA message with the search string, in order to get true context help.

In the Find box, you can use combis à la CreateWindow+Date to limit the search.
Feedback welcome ;-)

The source is in *.asc format, readable in WordPad, MS Word or RichMasm (http://masmforum.com/~masm32/board/index.php?topic=94).

P.S.: Works fine with Firefox, but there is a problem with MSIE: Explorer opens the html file in a new tab, not a window. I wonder if that can be programmatically changed...
Title: Re: Contextual help project
Post by: dedndave on July 25, 2012, 08:27:58 AM
that is an option in IE settings
firefox has a similar setting
Title: Re: Contextual help project
Post by: mywan on July 25, 2012, 03:15:22 PM
Nice start  :t
 In all my browsers, when I redirected to another page after opening a previous page, it would simply close my browser (*Note: after switching to standard windows behavior), requiring reclicking to reopen the browser. Hence I lost a large group of tabs opened on various subjects I was studying when I tested your app. It also refused to open any browser maximized, even if that was the previous state of an already opened browser. My .htm files are not (by default) associated with any browser on my machine, rather to my own app (Drawer.exe) giving me a choice of any of my browsers, editors, etc., to open with. When I bypassed my Drawer app your app was highly inconsistent in what occurred from one click to the next. Sometimes a separate window, other times a new tab, other times closing browser it never opened to begin with while failing to open the selection I chose. This problem persisted for all browsers. This was due, apparently, to the default behavior of wanting to close previously opened instances of my browser without first knowing whether that previous instance was still open or not or whether it involved opening a new tab in an existing browser. My default open pointing at Drawer.exe actually completely tamed this behavior (if parent/child redirection wasn't specified), since it automatically closes after any choice is made removing the handle for your app to close.

 If you stripped "xHelp/" from the full path and replaced the last instance of "/" with ".chm::/" and ShellExecute that string it will open the proper <filename>.chm location, at the page location, using the standard windows help file reader, hh.exe. The browser then wouldn't be an issue. You can also avoid ShellExecute by prepending the path string with "hh.exe ", but not really necessary. If the same .chm file is being redirected to another page, and a previous instance has been opened, then passing the Hinstance from the previous ShellExecute should allow you to avoid opening a separate instance of hh.exe, and wouldn't require that you exit the previous instance. For multiple <filename>.chm opened you would need an array of previous Hinstance's from ShellExecute with the previous <filename> associated with its own Hinstance. Even in the event that a separate instance of hh.exe is required, for a differing <filename>.chm, I would not want the previous instance automatically closed under any circumstances.

If you want to stick with opening the .htm files using the browser I would still absolutely avoid closing the previous instance, and merely let the new .htm open in another tab, or browser, per the users browser configuration. Firefox even has plugins to avoid multiple instances of the same page. There are also techniques for reusing the same tab in various browsers, but requires knowing which browser is being used, and in some cases using command line switches, activeX for IE, or possibly addons in FireFox. Too much trouble in general.

Personally I would go with the default hh.exe on the existing .chm files, to maintain consistency of expectations. Then use the Hinstance arg to avoid multiple windows without closing the previous window, but with checks to see whether that Hinstance still exist or not and/or corresponds to a differing <filename>.chm. I would never outright close a previous instance of anything under any circumstances. These things need fixed before a consistent operation can be achieved irrespective of the local user configuration. In my own configuration fixing these configuration dependencies for various standard user configurations would also greatly extend my configuration options using my Drawer app beyond simply taming the inconsistent behavior.

After writing a single app to completely replace all file associations in windows, with configurable per selection standard input/output redirection, I am exceptionally good at this stuff. Though I never used ShellExecute to accomplish it, since that defeated my goal of entirely replacing windows file association system and would create an infinite open with loop of choices, because Drawer.exe would then always point back to itself. Though this is allowed, per choice configuration, if you want to open a second set of choices for a given Drawer, and can chain parent/child redirection, if needed, through any arbitrary number of Drawer.exe instances.
Title: Re: Contextual help project
Post by: jj2007 on July 25, 2012, 04:02:11 PM
Thanks, mywan, that was a very detailed feedback :t

Re "I would never outright close a previous instance" - that is the standard behaviour of a browser when you click on a link: open a new page and close the old one simultaneously. This works in my configuration (where ShellExecute opens a new browser instance), but it fails with user settings where closing the old page closes a bunch of tabs (I hate tabbed browsing :bgrin:).

Note it should not close a page opened by the user for other purposes. My code checks the title tags inside the page to be opened, then, after ShellExecute, waits a while until that title appears online, saves the handle; in the next round, after opening a new page the old one gets closed. You may experience that one of your pages was closed simply because you were working with your own app and the exact same title... ;-)

Here is the snippet that performs these actions:

ShowHTML proc uses edi
LOCAL ct
   mov ecx, Matches[4*eax]    ; index passed in eax
   mov edi, hhTitle$(ecx)      ; load window title as identified via title tags
   invoke ShellExecute, 0, 0, Files$(ecx), 0, 0, 0   ; If lpFile specifies a document file, nShowCmd should be zero
   and ct, 0
   .Repeat
      inc ct
      invoke Sleep, 50
   .Until WinByTitle(edi) || ct>127   ; 50*127=6 seconds
   .if lastWin
      push eax
      .if rv(IsWindow, lastWin)
         invoke SendMessage, lastWin, WM_CLOSE, 0, 0
      .endif
      pop eax
      and lastWin, 0
   .endif
   .if ct<=127
      mov lastWin, eax
      invoke SetForegroundWindow, hMain
      invoke SetFocus, hListbox
   .endif
   ret
ShowHTML endp

I had already a version working with DDE and WWW_OpenURL, but you ran basically into the same problems. Another option would have been to open once an instance of FF/MSIE/xx, then send WM_DROPFILES to navigate to the next user choices. For reasons I have not fully understood, both MSIE and FF refuse to react to the WM_DROPFILES, so for the time being I am stuck with ShellExecute or. and this I may try soon, CreateProcess.

Re using HH.exe: I hate the interface :(
Title: Re: Contextual help project
Post by: mywan on July 25, 2012, 07:12:01 PM
Oh, I see. There was no source code for me to know what was happening. I use tabbed browsing extensively. However, my FireFox does not close by default when the last tab is closed. This is the result of "invoke SendMessage, lastWin, WM_CLOSE, 0, 0" in your code. Another problem is the title match you use. I'll try to outline what's happening at the application level.

1) WM_CLOSE pertains to the application, not to any tab within the application.
2) The title of the application is dependent on which tab is active within the application.

This means that if I open a help file and remain on that tab, your program returns the proper title attribute. However, if I either switch tabs, or the local default behavior dictates that the new tab opens in the background, then your match by title will never match, even though the previous help file remains open. Your "invoke SendMessage, lastWin, WM_CLOSE, 0, 0" then closes ANY instance of ANY browser that intercepted your attempt at opening a new window.

For instance, you have a browser open with Hinstance=1. It's configured to open new pages from ShellExecute in new tabs. Therefore ShellExecute  will not return a new Hinstance, rather it simply attaches itself to Hinstance=1. lastWin then does not refer to a window you opened, but rather to the window that intercepted the window you attempted to open. The inverse problem exist when you attempt to use WinByTitle. The title a property of the tab, not the window, yet is passed to the window if and only if that tab is active. "invoke SendMessage, lastWin, WM_CLOSE, 0, 0" will never simply close a tab, it'll close the browser regardless of how many or few tabs are opened in it. It'll even close my browser in spite of the fact that my browser is configured to remain open even if the last tab in it is closed. So it's not just a default browser behavior closing the browser in this instance.

I'm about to create some test scripts to figure out the best way to deal with the no tabs choice you prefer. The problem is not with any given browser, but the differences in how different browsers handle it. Here's the test I think might work best:

1) ShellExecute normally returning Hwind1.
2) ShellExecute next window returning Hwind2.
3) If Hwind1 matches Hwind2 then tabs used.

There is likely a more elegant solution though, but you likely need to use the Hinstance argument to ShellExecute to take advantage of it.

An even better solution would be to avoid browsers altogether, using hh.exe with an Hinstance argument. Then you can easily just forward the location within "<filename>.chm::/<location>.htm" to a new <location>, and the user can also still use the back button to get back to the previous page. To handle multiple "<filename>.chm" you have a set of "key"="value" pairs where "key" is <filename> and "value" is an Hwind. Then the max number of windows you would open would not exceed the number of differing <filename>.chm files opened no matter how many different locations were opened within a given <filename>.chm.
Title: Re: Contextual help project
Post by: jj2007 on July 25, 2012, 07:24:04 PM
Quote
.... then your match by title will never match, even though the previous help file remains open. Your "invoke SendMessage, lastWin, WM_CLOSE, 0, 0" then closes ANY instance of ANY browser that intercepted your attempt at opening a new window

lastWin is set only if WinByTitle returns a window with that title (as the name of the macro says). So no browser window will be closed arbitrarily.

The problem is tabs - if a new tab is added, and from then on the browser window has the HH title, then my proggie will indeed afterwards close that window including older tabs. MSIE and FF give a warning before closing multiple tabs, by the way, but you may have disabled that warning.

There are ways to close tabs (MSIE (http://stackoverflow.com/questions/2839063/how-to-close-ie8-tabs), FF (http://forums.mozillazine.org/viewtopic.php?f=8&t=2555)) but they seem very clumsy. The FindExecutable road looks more promising.
Title: Re: Contextual help project
Post by: mywan on July 25, 2012, 07:38:50 PM
lastWin is set only if WinByTitle returns a window with that title (as the name of the macro says). So no browser window will be closed arbitrarily.
Maybe I messed up the description a bit, but this was understood. However, if I open a window which is intercepted as a tab within an existing window, then if I click another selection in your app all my existing tabs, unrelated to your app, gets closed if and only if the tab your app last opened remains the active tab. Hence the inconsistent behavior.
Title: Re: Contextual help project
Post by: mywan on July 25, 2012, 07:50:29 PM
Also, I just spotted the conditions under which your app closes the browser apparently without opening the selected file, leaving nothing opened at all. If you select the same choice twice then a new tab is added that is identical (including title) to the lastWin. WM_CLOSE then closes the window in which the new tab was just created because it's the same window, with the same title as lastWin.
Title: Re: Contextual help project
Post by: jj2007 on July 25, 2012, 11:50:31 PM
Thanks, mywan. I attach a new version that hopefully resolves these issues.
The only thing that is bugging me is that it opens as maximised in both FF and MSIE, unless the last FF window closed was not maximised.

I also added a check if the user moved away from the help page, e.g. by clicking on a link; in this case, the old window will not be closed. For example, if the user
- typed string+array in the find box
- presses TAB to move on to the listbox
- presses t to see Tokenisers
- clicks on ltok to see Tokenise lines of text "in place" etc
then a next click on e.g. arr2disk in the listbox does not close the ltok window.
I hope that logic is acceptable :biggrin:

Here is the relevant code (full source attached):

ShowHTML proc uses esi edi   ; show the file in a browser
LOCAL ct, inx
  mov ecx, Matches[4*eax]   ; index passed in eax
  mov inx, ecx      ; there are some API calls that trash ecx
  mov edi, pExeName   ; includes  -new-window "file:///x:
  mov eax, Cat$(edi+Replace$(Files$(ecx), "\", "/")+Chr$(34))
  ; CreateProcess:
  Launch eax   ; ignored:, SW_xx   ; Cat$(edi+"file:///"+Replace$(Files$(ecx), "\", "/")+Chr$(34))
  mov edi, hhTitle$(ecx)   ; load window title as identified via title tags
  ; no good: invoke ShellExecute, 0, 0, Files$(ecx), 0, 0, 0
  and ct, 0
  .Repeat
      inc ct
      invoke Sleep, 50
  .Until WinByTitle(edi) || ct>127   ; 50*127=6 seconds
  .if lastWin
   push eax
   .if rv(IsWindow, lastWin)
      .if Instr_(Win$(lastWin), hhTitle$(lastIndex))==1      ; titles must match
         invoke SendMessage, lastWin, WM_CLOSE, 0, 0   ; close previous window
;      .else
;         mov ecx, Cat$(Win$(lastWin))
;         deb 1, "You moved on:", $hhTitle$(lastIndex), $ecx
      .endif
   .endif
   pop eax
   and lastWin, 0
  .endif
  .if ct<=127
   mov lastWin, eax   ; valid new window found
   m2m lastIndex, inx   ; remember last Files$() index
   invoke SetForegroundWindow, hMain   ; get dialog to front
   invoke SetFocus, hListbox   ; and enable scrolling through the box
  .else
   MsgBox 0, hhTitle$(inx), "No window found", MB_OK   ; complain
   or lastIndex, -1
  .endif
  ret
ShowHTML endp
Title: Re: Contextual help project
Post by: mywan on July 26, 2012, 02:46:45 AM
Congrats, you managed to find a chink in my Drawer app. I never give it any thought because all browsers will convert a file path to a file:///url on their own:
C:\Masm32\help\xHelp\masm32\Processor Flags.htm
Or
file:///C:\Masm32\help\xHelp\masm32\Processor%20Flags.htm
To:
file:///C:/Masm32/help/xHelp/masm32/Processor%20Flags.htm
Yet browsers do not understand:
C:/Masm32/help/xHelp/masm32/Processor%20Flags.htm

Now, with your app using 'file:///C:/<etc>' by default, my Drawer app doesn't recognize it as a valid url due to 'file:///' or a valid path due to '/' following the drive assignment. Oversight on my part, but not something I've ever encountered either. At least not as a primary command string rather than as an argument. I need to fix this in my app but I'm not sure why you would bother preprocessing this string when all browsers handle it fine as is.

Also, if I open <file>.htm with your app, then click a new one to open and take more that 5 seconds or so to make a drawer selection then the browser closes and I get an error from the app: MessageBox: No window found, $hhTitle$(inx)  ltok, where ltok is the name of the htm file. Fairly obvious why.

Set back to windows default it works really smoothly on FireFox. On Iron (effectively Chrome) it opens the first selection fine. Then if a second selection is made it opens another tab then closes the browser, leaving no browser open with any help file. If you exit the app it closes the browser also. On IE it merely opens a new window for each selection, leaving as many windows open as selections you made in the app. IE never gets closed except by the user. Perhaps you are expecting a pure 32 bit machine. On windows 7 the invisible windows redirection to 2 separate program files folders, 2 different system folders, etc., is a nightmare. The path you type is not necessarily the path windows uses. When you specified the full path:
"C:\Program Files\Internet Explorer\iexplore.exe"
You explicitly specified a 64 bit option on my machine, which invisibly redirects 'C:\Windows\System32' to 'C:\Windows\SysWOW64'. I'm not sure what MbCopy is? Pure 32 bit apps are fine on my machine and I develop my assembly in pure 32 bit, at least for now.

I really don't think you can solve all these problems the way your going about it. I haven't done any testing myself yet because I had to go under my brothers house to fix an AC problem. Generally I love reading your code. It shows a level of creativity I can only imagine in terms of assembly. I'm working on it though.
Title: Re: Contextual help project
Post by: jj2007 on July 26, 2012, 05:04:51 AM
Now, with your app using 'file:///C:/<etc>' by default, my Drawer app doesn't recognize it as a valid url due to 'file:///' or a valid path due to '/' following the drive assignment. Oversight on my part, but not something I've ever encountered either. At least not as a primary command string rather than as an argument. I need to fix this in my app but I'm not sure why you would bother preprocessing this string when all browsers handle it fine as is.

I had problems with MSIE under Windows 7-32, that's why I went for pre-processing. Now I checked under WinXP SP3, and it works indeed with standard backslashes.

What drives me mad is that none of these stupid browsers (I can test only FF and MSIE) implements DDE properly, or has another reasonably simple method to
1. open one window
2. reuse that window if the user wishes to do so

I keep opening new windows or tabs, either maximised at the browser's (not: user's) choice or restored but with changing positions, and as far as DDE and FF are concerned, it's a *very* old bug that was never fixed.

Version D attached, it removes mov byte ptr [esi+Len(esi)], "l" in line 102 which was for testing only.

P.S.: MbCopy is documented here (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1129).
Title: Re: Contextual help project
Post by: dedndave on July 26, 2012, 07:58:36 AM
have you tried using the anchor tag target attribute ?
Code: [Select]
<a target="_blank|_self|_parent|_top|framename">
Attribute Values
Value      Description
_blank     Opens the linked document in a new window or tab
_self      Opens the linked document in the same frame as it was clicked (this is default)
_parent    Opens the linked document in the parent frame
_top       Opens the linked document in the full body of the window
framename  Opens the linked document in a named frame
Title: Re: Contextual help project
Post by: jj2007 on July 26, 2012, 08:23:53 AM
Dave,

The problem is one step before: The browser receives via ShellExecute, CreateProcess or WWW_OpenURL*) the order to show xx.html; but in all cases, instead of allowing to specify an existing window, the browser opens a new one. Your suggestion is fine but it comes in when the window is already open :(

My first idea was actually a WM_DROPFILES-based server, but FF and MSIE couldn't care less, they just ignore the filenames passed.

*)
https://bugzilla.mozilla.org/show_bug.cgi?id=268840
...
Reproducible: Always
Steps to Reproduce:
Open a bookmark using a third party bookmark manager that uses DDE to
communicate with the browser, e.g. Bookmark Buddy or URL Organizer 2
(urlorg.com/download.shtml).
Actual Results: 
New URL is always opened in accordance with the Tabbed Browsing 'Open links from
other applications in' preference, irrespective of the windowID used, and the
relevant window is not activated.

Expected Results: 
The default behavior for WWW_OpenURL should be as follows:
 - a windowID of 0 should open a URL in a new tab
 - a windowID of -1 should open a URL in the most recent tab
 - a windowID > 0 should open a URL in the corresponding tab*
Whichever window the URL is opened in should be activated.
 
The 'Open links from other applications' Tabbed Browsing options should be
changed to:
x Use new windows instead of new tabs
x Always open in: [a new tab] OR [a new window] OR [the most recent tab/window]

*This requires WWW_ListWindows to be implemented; see:
https://bugzilla.mozilla.org/show_bug.cgi?id=84363
Title: Re: Contextual help project
Post by: mywan on July 26, 2012, 01:54:49 PM
ChmWindowD
Under FF, standard windows file association, it appears to work well as you seem to expect.

Under IE, standard windows file association, it still open every click in a new window requiring them all to be manually closed.

Under Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs. Hence "Bare Bones Dialog" attempts to open 3 tabs at "file:///C:/Masm32/help/xHelp/imdialog/Bare", "http://bones/", and "http://dialog.htm/". Using choices with no spaces it opens each each choice properly but in its own tab leaving the previous tab. The entire browser then closes when you exit the app.

Opening with my Drawer app changes none of the behavior above, and can no longer prevent you app from closing my browsers. Except IE which never closes anyway.

I could also test in Opera, Maxthon, and others, but would need to disable some significant modifications to make it meaningful.
____

It's a good idea to think through exactly how you expect it to work. If you are wanting it to work for everybody the way you want it to work for you it is a lost cause. Even if the browsers consistently supported the behavior you apparently seek, a large number of people would install plugins for the explicit purpose of disabling your ability to do that to their browser. Very few users have any interest in a non-tabbed browser, and will be very impatient with any app that tries to demand it. By attempting to demand it your app will consistently close the pages people have open for other reasons. Personally I used a parent container to effectively get tabbed browsing before browsers started supporting it, initially with Maxthon. Even if you got it to work flawlessly in all browsers the way you want very few people would tolerate it.

You basically have two choices. Work from the perspective of a tabbed browser user, and use a plugin to redirect all tabs into a single tab on your own browser. If no FF addon suites you modifying "Close other tabs (https://addons.mozilla.org/en-us/firefox/addon/close-other-tabs/)" to auto close inactive tabs, setting activate new tabs to true, and don't show tabs on last tab to true will get you a tabless FF that operates in a consistent manner with a tabed browser. That addon can also be implemented as a very simple UserJs without the overhead of an addon.

First option (Not ideal):
With the above configuration merely open the help file in a new tab, consistent with the expectations of a tabbed browser. You personal browser will then automatically close the existing tab, or better redirect the existing tab to the new tab location, leaving no tabs for you to deal with. Your app then doesn't need to deal with these issues, the browser does the work for you. Then when exiting your app leave the browser open. It's the ONLY way to be consistent with tabbed and non-tabbed users, and more importantly does not kill everything else a tabbed browser is doing unrelated to your app. Attempting to make my browser operate in a manner consistent with someone else's expectations will never be allowed, no matter how complex a UserJS, sandbox, wrapper, redirect, whatever I have to create to prevent it.

Second option (Best option):
Switch from using <unknown> browser to using hh.exe. This provides consistency across all windows. You can then simply use DDE to redirect the page hh.exe is displaying. Or, not so good, you can simply kill the previous instance of hh.exe you created and open another, just like you are attempting to do with <unknown> browsers. Personally, so long as the app closes anything at all, other than itself, it will never find a use on my machine. Having a config file or command line switches to turn the killing of previous instances or pages on and off is also a viable option.

Questions:
So how do you expect it to actually work for you, and how does that differ from what you are trying to impose on others? Are you mistaken your attempt at getting browsers to cooperate with an attempt to force everybody's browser to be what you want in your browser? A question that needs carefully thought through before any effective GUI development even makes sense. The fact that browser developers woke up to the fact of these inconsistencies in peoples preferences is the source of your present headache. Never force preferences on people, rather do what you need to do to your own browser to consistently get the behavior you want locally. It's not the job of your external app, nor possible, to force your browser preferences on others.
Title: Re: Contextual help project
Post by: jj2007 on July 26, 2012, 08:00:46 PM
ChmWindowD
Under FF, standard windows file association, it appears to work well as you seem to expect.

Under IE, standard windows file association, it still open every click in a new window requiring them all to be manually closed.

Yes, FF works fine but IE refuses to accept Send/PostMessage WM_CLOSE.

Quote
Under Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs.

Surprising because the proggie hands over a "full path" :(

Quote
It's a good idea to think through exactly how you expect it to work.
...
First option (Not ideal):
With the above configuration merely open the help file in a new tab, ...

Second option (Best option):
Switch from using <unknown> browser to using hh.exe. This provides consistency... simply use DDE to redirect the page hh.exe is displaying
...
Personally, so long as the app closes anything at all, other than itself, it will never find a use on my machine.

"The app" is a proggie that receives from your favourite editor the info "user has selected string array and pressed F1, so it seems he needs help".

What I expect is to see, after no more than one additional click or keystroke, the screen below. And I expect also that as long as I don't click inside the browser, I can scroll through the list of matches by simply pressing arrow up or arrow down. Sheer luxury, I know ::)
Title: Re: Contextual help project
Post by: jj2007 on July 26, 2012, 08:08:49 PM
What I get instead, if I
- select a much simpler print, then
- guess that it is the \Masm32\help\hlhelp.chm among the ten help files present in that folder,
- open the editor's help menu, where hopefully all ten files are registered
- then click on High Level Macro help,

is the rubbish below. You see the problem?

"The app" uses IE or FF for the exclusive purpose of displaying a user-chosen html page. Unfortunately, there is no easy way to use a WebBrowser control in the same way that you would use a simple RichEdit or "pure" edit control inside your app - that would be the ideal case. Your reflections about user preferences and tabbed browsing etc are valuable, but they apply to a different application: a stand-alone browser. What I need is a control, and I am sure users would look a bit dumb if Notepad suddenly started inserting tabs and playing other gimmick stuff depending on some global preferences set in an unrelated app, say: MS Word...
Title: Re: Contextual help project
Post by: jj2007 on July 26, 2012, 08:35:36 PM
What I also expect from the final version (not the attached one - still not perfect) is that if the user hits F1 and
- there is only one (case-sensitive, full word) match, it will show the html content directly, without any user input;
- if there is no match in the Masm32 chm files for e.g. VirtualAlloc, the app would check if a) Win32.hlp is available and b) the string is long enough to be an API call, and launch it to get immediately this screen (a feature which, by the way, works already fine in RichMasm (http://masmforum.com/~masm32/board/index.php?topic=94)):
Title: Re: Contextual help project
Post by: mywan on July 26, 2012, 11:05:14 PM
string_array_xHelp.zip, print_in_HLL.zip, and F1_VirtualAlloc.zip all appear empty to me, no matter which browser I try to download them with.

You can use a COM object in assembly, including the "InternetExplorer.Application" object. Both IE and hh.exe are fully accessible by COM controls, and hh.exe has command line parameters to provide effectively the same function by simple command arguments. The download link under "IE Automation" on this page below provides a working program and source code for IE automation through COM. Play with the included compiled sample program and you'll see exactly what I mean. It's exactly what you need.
http://www.japheth.de/COMnASM.html

That will give you very fine grained control over IE, and works even if the user uninstalled IE.
http://msdn.microsoft.com/en-us/library/aa752084(v=vs.85).aspx

You can also do the same thing with a standard help file, and/or command line parameters to accomplish the same.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms524369(v=vs.85).aspx
http://msdn.microsoft.com/en-us/library/windows/desktop/ms670084(v=vs.85).aspx
Quote
If a window type is not specified, a default window type is used. If the window type or default window type is open, the help topic replaces the current topic in the window.

In your pic above, where you got the page note found. I can't see your source that produced that but it was obviously a syntax problem somewhere. The easiest way to check and see what happened is to right click the error page select properties and check the Address: (URL) that landed you there. The full URL might not be fully visible, but if you select it the rest will scroll into view. I even did a quick and dirty AutoIt script and use my Drawer app to shell your apps command line to it as an argument, then striped the strings I needed from your command string to open the proper .chm file at the proper location. It does in fact work.
Title: Re: Contextual help project
Post by: jj2007 on July 27, 2012, 01:27:53 AM
string_array_xHelp.zip, print_in_HLL.zip, and F1_VirtualAlloc.zip all appear empty to me...
They are png's disguised as zip files. An insider trick to show screenshots - it will work until Hutch stops it one day ;-)

Quote
You can use a COM object in assembly, including the "InternetExplorer.Application" object. Both IE and hh.exe are fully accessible by COM controls, and hh.exe has command line parameters to provide effectively the same function by simple command arguments. The download link under "IE Automation" on this page below provides a working program and source code for IE automation through COM. Play with the included compiled sample program and you'll see exactly what I mean. It's exactly what you need.
http://www.japheth.de/COMnASM.html
I agree. Unfortunately, while it assembles fine after some mods, I can't get it to link - lots of error messages (and yes I did install the JWasm includes and set the paths etc).

Quote
In your pic above, where you got the page not found. I can't see your source that produced that but it was obviously a syntax problem somewhere. The easiest way to check and see what happened is to right click the error page select properties and check the Address

I had a bug, it send print%20.html instead of print.htm. Thanks for pointing me to this.
Title: Re: Contextual help project
Post by: Antariy on July 27, 2012, 11:09:04 AM
Quote
Under Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs.

Surprising because the proggie hands over a "full path" :(

What if replace each space with a "%20" escape code?
Title: Re: Contextual help project
Post by: mywan on July 27, 2012, 12:24:13 PM
Quote
Under Iron (Chrome) any spaces in the filename get delimited as separate pages to open in different tabs.

Surprising because the proggie hands over a "full path" :(

What if replace each space with a "%20" escape code?
That may work but I usually just pass quotes as '"strings"'.
Title: Re: Contextual help project
Post by: jj2007 on July 27, 2012, 06:20:49 PM
I tested it with Chrome now and it works just fine: Chrome translates
"C:\...Google\Chrome\Application\chrome.exe" "file:///C:/Masm32/help/xHelp/asmintro/Working With Strings.htm"
into
file:///C:/Masm32/help/xHelp/asmintro/Working%20With%20Strings.htm.
So I wonder what went wrong on your side :(

On a side note: To test this, I had to install Chrome. They trick you into making you believe that you absolutely must use/create a Google account to use Chrome. Well, I have one that I rarely used; when logging in, they tell me about "unusual activity discovered", and that I must absolutely give them my mobile number so that they can send access codes via SMS. Google, go to hell :icon_mrgreen:

Finally I found out that it works fine if you paste a URL. No account needed.

On a programmatical side note:
   Chrome=1
   if Chrome
      invoke ShowWindow, hMain, SW_MINIMIZE
      invoke ShowWindow, hMain, SW_RESTORE
   else
      invoke SetForegroundWindow, hMain   ; get dialog to front
   endif
For some obscure reason that only Google coders will know, SFG for my own window does not work here, in contrast to other FF and MSIE. Again, Google, go to hell :icon_mrgreen:
Title: Re: Contextual help project
Post by: MichaelW on July 27, 2012, 06:43:01 PM
Google are data miners.
Title: Re: Contextual help project
Post by: mywan on July 27, 2012, 09:24:48 PM
On a side note: To test this, I had to install Chrome. They trick you into making you believe that you absolutely must use/create a Google account to use Chrome. Well, I have one that I rarely used; when logging in, they tell me about "unusual activity discovered", and that I must absolutely give them my mobile number so that they can send access codes via SMS. Google, go to hell :icon_mrgreen:
Yes, like Michael said, Google is data mining in the extreme. Just so you know, when you installed Google's official version of Chrome as a courtesy it provided you with a unique installation ID. Now, even if you never go to a Google domain again with Chrome they can track you through their ads placed on most every web page on the internet. That's why I'm using Iron instead of Chrome. Chrome is open source, and Google merely makes some tracking changes for their official installation. Iron can also be run from a thumb drive, with no registry writes, temp files, cache, or anything else written to or used outside of that thumb drive. You don't even have to use an installer. Just do a search of "google" in your registry now, and uninstalling will not get rid of it or your unique installation ID.

Personally, one of my Drawer options on my quick launch is a Host file toggle. Almost every site I go to has little boxes with "Page not found" in it. Oh, another thing, tacking cookies are not deleted by deleting cookies these days, or stopped by turning cookies off. Google "super cookies" to see what I mean. Primarily culprits are flash and silverlight. And no, there are no browsers in which privacy settings has any effect on these zombie cookies whatsoever and the usual blog advice is about universally useless. I don't give a crap what they know about me but anybody that tries to follow me like they do and I'm calling the cops. I use entirely separate sandboxed browsers for Google, facebook, and other such services. These browsers then have wrappers that automatically toggle Host file configs and have their own sets of privacy plugins and such. Many companies are even using hardware/software profiles to fingerprint you without any cookies, super or otherwise. So my profile toggle actually randomizes a bunch of junk fonts to swap in and out, switches various plugins, such as pdf readers (I like SumatraPDF), on and off, and swaps out various user scripts and addons. I still need a better way to fake screen resolutions and certain software version numbers. I even use a UserJS to rewrite Google search results so Google can't see what I clicked. IE I (almost) never use anyway, except for com automated stuff and testing. Some of them probably have me uniquely profiled as a dozen different users.

_________
Have you considered command line switches for setting preferences? The entire switch could be a single string of boolean zeroes and ones, or larger single digit numbers if you have a multiple choice option. The list could include:
Close app on selection.
Close precious help file on page change.
Use help file reader?browser [0?1].
Always on top.
My preference, in order given, would probably go something like: 10001. My choice in help file readers is not limited to hh.exe.
Title: Re: Contextual help project
Post by: jj2007 on July 28, 2012, 08:48:04 PM
Betatesters sought urgently :biggrin:
Title: Re: Contextual help project
Post by: sinsi on July 28, 2012, 10:09:06 PM
OK, can't close the help window, no sysmenu, no right-click. The only way is to quit xhelp.
Title: Re: Contextual help project
Post by: mywan on July 28, 2012, 10:17:07 PM
Getting much much better  :icon_cool:
(Complete bug description below)

The search box merely minimizes to the taskbar when you hit escape, but the IEContainer closes. Closing the search box requires right clicking the taskbar item. A more serious issue is when you run xHelp and do a search and select something to generate xHelp.dat and LastFind.tmp and close the search box, then when you run the search again it refuses to maximize (show normal). You only see it on the task bar. Deleting xHelp.dat will make it show normal again, but when you select an item the IEcontainer has the smallest possible size. Too small to see any of the help file. When you hit escape again at this point the IEContainer appears to close, except when you check the task manager it is still running. Deleting both xHelp.dat and LastFind.tmp mostly fixes it temporarily. Usually the IEContainer still keeps coming up the smallest possible size though.

A second minor bug is that if you do a search which produces only 1 result, open the IEContainer for that item, then if you close that container (not the search box) you can't open the IEContainer again unless you search for something different. I remember why this it from a previous issue you fixed. Likely an issue that's not relevant anymore.

I could live with your general approach, with this new IEContainer system if it did one more feature. That would be embedding the search box on the left side of the IEContainer like the left navigation column of a webpage.
Title: Re: Contextual help project
Post by: jj2007 on July 29, 2012, 03:17:54 AM
Getting much much better  :icon_cool:
(Complete bug description below)
...
I could live with your general approach, with this new IEContainer system if it did one more feature. That would be embedding the search box on the left side of the IEContainer like the left navigation column of a webpage.

Bugs are hopefully fixed, and I added the option to hit F4 for closing the browser window. Alt F4 from the xHelp window closes everything, and I added a check that prevents "iconic" sizes from being saved ;-)
Re embedding: That is a question of taste and of "real estate". Once you embed the listbox, you are sacrificing a whole column of the browser window. The current xHelp window can be kept very small and be moved to a corner where it does not obscure what the user needs to read.

Where do you guys usually keep your Win32.hlp file? As \masm32\help\Win32.hlp?
Title: Re: Contextual help project
Post by: dedndave on July 29, 2012, 04:26:48 AM
i like it - it seems to be very fast
is there a reason why the windows do not have a close button, rather than using F4/Alt-F4 ?
Title: Re: Contextual help project
Post by: jj2007 on July 29, 2012, 07:06:51 AM
i like it - it seems to be very fast
is there a reason why the windows do not have a close button, rather than using F4/Alt-F4 ?

Typical response time for searching the 800+ html files is about 5 ms on my slow Celeron :biggrin:
xHelp tries to give you good value for your typing. Example:

unicode  21 matches (exact word, case-sensitive)
unicodE  70 matches (case-insensitive search)

unic...unicod also yield 70 matches, because the algo switches to partial, case-insensitive matches.

The first version uses MasmBasic's "intellicase" option for Instr, where both Unicode and unicode are valid full-word matches.

Generally I use Escape for proggies that can either stay active, or cannot lose any precious data. You just hit one key in a convenient corner and no worries.
For the browser window, Escape is not a good choice because it stops loading a webpage; so F4 (close document) seems a good choice for closing the browser but keeping the process (the window remains hidden, and exits only when the xHelp dialog closes for good).

Version b, attached below, integrates Win32.hlp - see xHelpReadme.txt

There is also now an option to send a search string with WM_COPYDATA. AFAIK it can be done with a console app, too. I wanted to test it on qEditor, but there seems no easy way to assign a Fxx key to an executable :(

EDIT: Just in case somebody wants to add a sysmenu or close box: The June version of MasmBasic lacked a few functions used in xHelp. To assemble xHelp.asm (or, better, xHelp.asc using RichMasm), unzip the attachment of the first post of http://masm32.com/board/index.php?topic=94.0 to the root of your Masm32 drive with "use folder names". Details (SetGlobals, Enum) in reply #2.
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 12:52:54 PM
I like it. Can't find any operational problems in the latest version that isn't primarily preference issues. It did figure out why it was saving the iconic size window while not saving the size changes I made. To get it to save the IEContainer size and position requires, after changing the size, selecting a page to display from the search box. Reselecting the previous selection does not work. If you close (Esc, Alt-F4, or right click) before selecting a differing item in the search box the new size/position never gets saved.

My Win32.hlp files are in the default \masm32\help\Win32.hlp. Some peoples are not. Regardless of where they are they will still need to be the same path you create the xHelp subdirectory in.

On other feature it needs is to pass the command line arg into the search box and searches it when opened. Then when I'm reading/writing source I can simply hit F1 to search the word I just typed or placed under my cursor. The word doesn't even have to be selected in my editor, it merely chooses the word nearest my caret. No copy/paste/typing required.

I can either live with every other preference or take the time learn/do my own modifications. As far as embedding the search box the minimal space it does take is less obtrusive embedded in the IEContainer where it doesn't overlap anything than when always on top on all the other apps I may have open. The general sparsity of the text in the xHelp htm/chm help files, and the minimal size of the search box, means it would be less obtrusive than the left side menu of the standard hh.exe display of the standard chm files. I would like to use this this regardless for now, as I have a few other things to develop and, being so noobish presently, I'm far slower and less productive than you atm.
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 03:57:54 PM
I ran across another problem. Apparently it is impossible for me to copy any text off the htm files displayed in the IEContainer control.
Title: Re: Contextual help project
Post by: jj2007 on July 29, 2012, 05:04:17 PM
I like it.
Thanks :biggrin:

Quote
To get it to save the IEContainer size and position requires, after changing the size, selecting a page to display from the search box.
Fixed. It saves new size/position immediately now, unless you write-protect the *.dat file, of course ;-)

Quote
Reselecting the previous selection does not work.
What do you mean?? Navigation inside the browser works fine for me... ::)

Quote
My Win32.hlp files are in the default \masm32\help\Win32.hlp. Some peoples are not. Regardless of where they are they will still need to be the same path you create the xHelp subdirectory in.
It is assumed that the user extracts the zip to [Masm32 drive]\, so that should work fine, no extra copy of Win32.hlp needed. Just test the current version attached below, you should see <Win32.hlp?> as last item of the listbox.

Quote
On other feature it needs is to pass the command line arg into the search box and searches it when opened. Then when I'm reading/writing source I can simply hit F1
This is already foreseen. The snippet below works fine, but you can roll your own CreateProcess/WM_COPYDATA sequence, of course.

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  mov esi, CL$()   ; get the commandline for SendData
  or ebx, -1
  .Repeat
   .Break .if WinByTitle("Masm32 xHelp", 4)
   .if Zero?
      Launch "\masm32\help\xHelp\xHelp.exe"
      .Break .if !eax   ; !eax = CreateProcess failed
   .endif
   invoke Sleep, 10   ; 10*127 = 1 second for launching
   inc ebx
   xor eax, eax
  .Until ebx>127
  .if eax
   SendData eax, esi   ; use WM_COPYDATA to pass on the string
  .else
   MsgBox 0, Err$(), "Big problem:", MB_OK
  .endif
  Exit
end start

I ran across another problem. Apparently it is impossible for me to copy any text off the htm files displayed in the IEContainer control.

That's right. Japheth's original release version of IEContainer.exe has the same problem.
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 05:29:49 PM
Quote
Reselecting the previous selection does not work.
What do you mean?? Navigation inside the browser works fine for me... ::)

Not the browser, the search box selection. For instance: Enter a search term and select a page to display. Now hit ESC to close the browser. You now can't reopen the same page you just closed without opening a different page page. Sometimes requiring another search term altogether if there is only 1 instance of a given search term. It's not a major problem, but it's why I missed some of the details on a previous bug you've already fixed. In fact, IIRC, you only added this behavior because earlier, with standard browsers, selecting the same term twice would simply kill the browser altogether. This is no longer relevant with the IEContainer.

Quote
That's right. Japheth's original release version of IEContainer.exe has the same problem.
I remember some things about these containers now. I had forgotten because I always used a new instance of IE itself for automation. You will have to listen for the copy event in WindProc and send the selected text to the clipboard yourself.
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 06:03:38 PM
Adding the chm link was an excellent move. However, the implementation broke a bit. Not sure why since my ArgSpy says the arg string being passed is "C:\masm32\help\imdialog.chm". Including the quotes as strings, which shouldn't be the problem. In your NanoTimer function you test for the existence of "\Masm32\help\Win32.hlp". There is no Win32.hlp in my MASM help file folder or anywhere else. Perhaps that has something to do with it.
Title: Re: Contextual help project
Post by: jj2007 on July 29, 2012, 06:14:32 PM
Enter a search term and select a page to display. Now hit ESC to close the browser. You now can't reopen the same page you just closed without opening a different page page.

Fixed, I added a WM_LBUTTONDOWN handler to the listbox subclass proc:

SubList proc uses ebx hwnd:DWORD, uMsg:DWORD, wParam:DWORD, lParam:DWORD
   SetGlobals
   .if uMsg==WM_CHAR
      .if wParam==VK_TAB
         invoke SendMessage, hFind, EM_SETSEL, 0, -1
         invoke SetFocus, hFind
      .endif
   .elseif uMsg==WM_LBUTTONDOWN
      .if lastWin
         .if !rv(IsWindowVisible, lastWin)
            invoke ShowWindow, lastWin, SW_RESTORE
         .endif
      .endif
   .endif
  invoke CallWindowProc, opSubList, hwnd, uMsg, wParam, lParam
  ret
SubList endp
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 06:18:54 PM
Saving position is not quiet right either. It doesn't actually save the position until you hit Alt-F4 and close both the search box and the browser.

Do a search, open the browser via a selection and resize/move the browser. Hit Esc to close the browser (not the search box), then bring up the search box again and make another selection. The browser window get recreated at the original location forgetting the new position. Whatever position it has when you finally do close the search box (along with the browser) is the position it remembers.
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 06:26:06 PM
Nice, 2 more issues and I will not have anything to complain about except preferences  :bgrin:
Title: Re: Contextual help project
Post by: jj2007 on July 29, 2012, 07:03:24 PM
Do a search, open the browser via a selection and resize/move the browser. Hit Esc to close the browser (not the search box)...

Can't see that one, sorry: F4 closes the browser, Esc works only in the xHelp dialog. And when I re-select, the browser appears with the latest position... or did I misunderstand something?
Title: Re: Contextual help project
Post by: mywan on July 29, 2012, 07:11:57 PM
Do a search, open the browser via a selection and resize/move the browser. Hit Esc to close the browser (not the search box)...

Can't see that one, sorry: F4 closes the browser, Esc works only in the xHelp dialog. And when I re-select, the browser appears with the latest position... or did I misunderstand something?
In the latest version this has been fixed. Apparently the same condition that prevented the same page from displaying twice also prevented an update to the windows position settings. The last fix apparently killed 2 bird with 1 stone.
Title: Re: Contextual help project
Post by: jj2007 on July 30, 2012, 09:15:00 AM
You will have to listen for the copy event in WindProc and send the selected text to the clipboard yourself.

I tried this in response to a keypress. No errors thrown but nothing on clipboard either ::)

                        IDM_COPY=15      ; Chappell (http://www.geoffchappell.com/studies/windows/ie/mshtml/methods/basemso/index.htm), MSDN (http://msdn.microsoft.com/en-us/library/aa769872%28v=vs.85%29.aspx)
                        OLECMDEXECOPT_DONTPROMPTUSER = 2   ; docobj.inc
                        invoke GetWindowLong, hWnd, WO_CONTAINER
                        mov ecx, eax
                        invoke vf([ecx].CContainer.m_pWebBrowser,IWebBrowser2, ExecWB), IDM_COPY, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0
Title: Re: Contextual help project
Post by: mywan on July 30, 2012, 02:36:41 PM
Without worrying about getting it on the clipboard yet, if select a range of text can you read what range of text has been selected with a hotkey? Say just a MsgBox popup saying what has been selected?
Title: Re: Contextual help project
Post by: jj2007 on July 30, 2012, 03:45:54 PM
IDM_COPY: Copies the current selection to the clipboard.

That sounds clear enough...

I wonder whether it has to do with some general IE settings on what is allowed or not (http://www.google.com/search?q="webbrowser"+"URLPOLICY_ALLOW"). What I found on Google is that 1. copy should work by default with the webbrowser control, and 2. it can fail:
Quote
First, the execCommand method fails if the given command name is not supported for scripting. Second, the following commands fail (subject to the notes on coding errors, below) if they cannot get clipboard access before calling Exec:

    * Copy
    * Cut
    * InsertParagraph
    * Paste
http://www.geoffchappell.com/studies/windows/ie/mshtml/methods/basemso/execcommand.htm

In any case, this is all hilariously complicated. The guy who invented COM should be hanged (sorry if that hurts someone's feelings :bgrin:)
Title: Re: Contextual help project
Post by: mywan on July 30, 2012, 04:25:12 PM
If you can obtain two pieces of information you can work around the problem regardless of its cause.

1) Can you read the user selected text (SelectedText) whether a copy is attempted or not?
2) Can you detect, in code, when somebody selects copy whether it fails to actually copy or not?

There are even ways to work around 2). If you can detect what text is selected from within your assembly then it is fairly trivial. Simply "invoke SetClipboardText selText", standard API call.

I tend to experiment with what bits of information I have access to. This information then defines what I have to work with to get around the problem, irrespective of what the cause of the problem was. I don't really don't know how it's supposed to be handled. In higher level languages this kind of information is hidden behind abstraction layers. However, there is often no need to implement a range of features through com that can more simply be handled yourself. The only really important thing is being able to retrieve the SelectedText in code. From there you can send it to the clipboard or anywhere else you choose.

If, as what you quoted said, this built in clipboard function fails if cannot get clipboard access before calling Exec it would make sense for it to fail. You code hasn't provided for access to the clipboard in order to prevent this method of failure. Basically you'll probably have to try and listen for the window messages generated in the failed attempt, and act accordingly.
Title: Re: Contextual help project
Post by: jj2007 on July 30, 2012, 04:32:39 PM
Simply "invoke SetClipboardText selText", standard API call.

Which API is that? I always use SetClip$ (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1088) "Hello World"...
Title: Re: Contextual help project
Post by: mywan on July 30, 2012, 05:41:13 PM
SetClip$ looks like it would work fine. My experience in assembly is just getting started and the only one I was explicitly aware of in MASM was SetClipboardText proc ptxt:DWORD in masmlib.chm. However, there are several APIs pertaining to the clipboad. Perhaps OpenClipboard can give you the clipboard access needed to get the default to work.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms649048(v=vs.85).aspx
You will need to close the clipboard (CloseClipboard) when done.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms649035(v=vs.85).aspx

Here is a list of clipboard related APIs:
http://msdn.microsoft.com/en-us/library/windows/desktop/ms648709(v=vs.85).aspx
Title: Re: Contextual help project
Post by: mywan on July 30, 2012, 05:46:38 PM
In fact, given the text you quoted about WM_COPY failing if it can't get clipboard access it makes sense that it would require a handle to the clipboard opened through the OpenClipboard API.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms649048(v=vs.85).aspx
Title: Re: Contextual help project
Post by: jj2007 on July 30, 2012, 08:15:26 PM
SetClip$ looks like it would work fine.

Yes it does, because I've written it myself using OpenClipboard, SetClipboardData etc
The problem is elsewhere. For the copy action of the webbrowser, a special procedure is defined here (http://msdn.microsoft.com/en-us/library/aa769872%28v=vs.85%29.aspx) and could be implemented as follows in IEContainer.asm - but it always returns error 80004005h:

Code: [Select]
invoke GetWindowLong, hWnd, WO_CONTAINER ; see also Exec_ in OleCommandTarget.asm
mov ecx, eax
invoke vf([ecx].CContainer.m_pWebBrowser,IWebBrowser2, ExecWB), IDM_COPY, OLECMDEXECOPT_DONTPROMPTUSER, 0, 0
Title: Re: Contextual help project
Post by: mywan on July 30, 2012, 09:37:43 PM
This looks like a permissions problem. I also remember something about needing a buffer to hold the data the clipboard accesses. I can't really play with your code much because while still trying to learn some basics my installation will remain the basic package.

What I would like to know is if you can access the pages dom to get retrieve htmlDocument.selection without worrying about putting it on the clipboard yet? If you can get this selected text then you can bypass the whole issue with IDM_COPY. All you have to do is figure out how to see the selected text independent of the clipboard.

Title: Re: Contextual help project
Post by: jj2007 on July 30, 2012, 11:35:28 PM
What I would like to know is if you can access the pages dom to get retrieve htmlDocument.selection

No. It's not included in the current webbrowser code, and implementing it via COM is way over my head, sorry...
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 12:47:10 AM
Do you have a version of just the IEContainerSample that I can compile? The download version doesn't. I've done a lot of com automation of webpages in other languages and have some idea of what I'm looking for to work around the problem. Even my bank monitoring is fully automated from scripts stored on a TrueCrypt drive. I haven't actually used a container, just an IE instance, in many years though, and then the container merely took ownership as parents of other apps. However, I want to see what I can learn and need some asm source I can compile.
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 01:08:07 AM
I just tried to attach to the embedded IE instance in your container with another app and was successful. I'm going to see what all I can get access to. Perhaps this is all I need given that you are basically controlling the container from a separate app also, albeit one written in asm.
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 01:51:11 AM
Do you have a version of just the IEContainerSample that I can compile?

Attached, with personalised batch file for debugging. This assumes Japheth's WinInc package and folders
[Masm32drive]:\JWasm\WebBrowser
[Masm32drive]:\JWasm\Include
[Masm32drive]:\JWasm\bin
[Masm32drive]:\JWasm\Lib
etc, i.e. the archive needs to be unzipped to the root of [Masm32drive] with "use folder names" on.

The *.asc file is for use with RichMasm (http://masmforum.com/~masm32/board/index.php?topic=94); if the JWasm/WinInc package is set up ok, drag \JWasm\WebBrowser\IEContainer.asc over \Masm32\RichMasm\RichMasm.exe and hit F6.
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 02:35:08 AM
Thanks for the code, I'll play with it, but I succeeded in retrieving the selected text from within IEContainer.exe using another app. I still have to dig in and figure out what APIs were being used. The relevant code snippet (AutoIt) was as simple as:

Code: [Select]
#include <IE.au3>
$oIE = _IEAttach("MasmBasic", "embedded")
Local $sText = $oIE.document.selection.createRange().text
MsgBox(0, "Selected Text:", $sText)

This popped up a message box with whatever text was select in the IEContainer window.
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 03:44:46 AM
Post the executable :biggrin:

#include <IE.au3>
Local MyInt = 1/0 ; let's see if Olly  (http://www.ollydbg.de/version2.html)likes the error handler :icon_mrgreen:
$oIE = _IEAttach("MasmBasic", "embedded")
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 04:03:24 AM
Post the executable :biggrin:

#include <IE.au3>
Local MyInt = 1/0 ; let's see if Olly  (http://www.ollydbg.de/version2.html)likes the error handler :icon_mrgreen:
$oIE = _IEAttach("MasmBasic", "embedded")

:badgrin:

What the above demonstrates is that IEContainer.exe is fine as is. The issue could be handled just as well from within xHelp.exe but it doesn't really matter which side it's implemented on.

Looking at the internals of the AutoIt code what is indicated is that you need to create access to an IDispatch object. This is done first by calling the CoInitialize API.
http://msdn.microsoft.com/en-us/library/windows/desktop/ms678543(v=vs.85).aspx

In AutoIt this is:
Code: [Select]
DllCall("ole32.dll", "long", "CoInitialize", "ptr", 0)
In asm it should look something like:
Code: [Select]
invoke  CoInitialize,NULL
Then to get a pointer to this interface you need to call the ObjectFromLresult API.

In AutoIt this looks like:
Code: [Select]
Local $lResult
Local $typUUID = DllStructCreate("int;short;short;byte[8]")
DllStructSetData($typUUID, 1, 0x626FC520)
DllStructSetData($typUUID, 2, 0xA41E)
DllStructSetData($typUUID, 3, 0x11CF)
DllStructSetData($typUUID, 4, 0xA7, 1)
DllStructSetData($typUUID, 4, 0x31, 2)
DllStructSetData($typUUID, 4, 0x0, 3)
DllStructSetData($typUUID, 4, 0xA0, 4)
DllStructSetData($typUUID, 4, 0xC9, 5)
DllStructSetData($typUUID, 4, 0x8, 6)
DllStructSetData($typUUID, 4, 0x26, 7)
DllStructSetData($typUUID, 4, 0x37, 8)

Local $aRet = DllCall("oleacc.dll", "long", "ObjectFromLresult", "lresult", $lResult, "struct*", $typUUID, "wparam", 0, "idispatch*", 0)

You'll need a SendMessageTimeOut to prevent a hang if retrieving the object fails. In asm the includes should contain the DllStructCreate construct, so should look something like:
Code: [Select]
invoke ObjectFromLresult, var1, addr IID_IHTMLDocument2, 0, addr var2
var1 is defined by the SendMessageTimeout API. I'm at the edge of what I understand in assembly, but this is as far as I've gotten so far.
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 04:18:44 AM
Attached is the executable.
Note: This does no error checking and will bomb out if the page IE page is not found. Simple run IEContainer.exe leaving it on the default "MasmBasic - a fast and easy-to-use library", select some text, then run ctrl.exe. The IEContainer does not have to be active to read the text that is selected on it.

I also found a sample script implementing what I described in assembly:
http://files.codes-sources.com/fichier.aspx?id=52594&f=html%2Fhtml.asm

Edit: I didn't pay attention when I compiled that, it might be 64 bit.. Let me know.
Title: Re: Contextual help project
Post by: Ryan on July 31, 2012, 04:20:44 AM
Japheth has implemented macros to streamline the function calls.  I've been trying to get through his Excel automation example.  I don't have it here at work.  It's on my home computer.  Since mywan has nailed down the properties needed to go through to get the selected text, I should be able to put something together for assembly.
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 04:25:13 AM
Here's the structure and some code for testing:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
uselib oleacc      ; thread
REFIID STRUCT
muInt   dd ?
muSh1   dw ?
muSh2   dw ?
muB8   db 8 dup(?)
REFIID ENDS

.data
typUUID REFIID <0626FC520h, 0A41Eh, 011CFh, <0A7h, 31h, 0, 0a0h, 0c9h, 8, 26h, 37h>>
IID_IAccessible REFIID <618736E0h, 3C3Dh, 11CFh, <81h, 0Ch, 0, 0AAh, 0, 38h, 9Bh, 71h>>

   Init
   invoke CoInitialize, NULL
   Inkey "ok"
   invoke CoUninitialize
   Exit
   invoke ObjectFromLresult, 1, 2, 3, 4   ; behind Exit - just to test if it assembles...
   invoke LresultFromObject, offset IID_IAccessible, 2, 3   ; is that a pointer to RIID, or RIID itself??
end start

Local $aRet = DllCall("oleacc.dll", "long", "ObjectFromLresult", "lresult", $lResult, "struct*", $typUUID, "wparam", 0, "idispatch*", 0)

ObjectFromLresult function (http://msdn.microsoft.com/en-us/library/windows/desktop/dd373605%28v=vs.85%29.aspx)
Retrieves a requested interface pointer for an accessible object based on a previously generated object reference.

STDAPI ObjectFromLresult(
  __in   LRESULT lResult,
  __in   REFIID riid,
  __in   WPARAM wParam,
  __out  void **ppvObject
);

LresultFromObject function (http://msdn.microsoft.com/en-us/library/windows/desktop/dd318557%28v=vs.85%29.aspx)

Returns a reference, similar to a handle, to the specified object. Servers return this reference when handling WM_GETOBJECT.
LRESULT LresultFromObject(
  __in  REFIID riid,
  __in  WPARAM wParam,
  __in  LPUNKNOWN pAcc
);
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 04:33:48 AM
Edit: I didn't pay attention when I compiled that, it might be 64 bit.. Let me know.

It's 32-bit code. However, it's packed - a bit more difficult to debug :(
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 05:20:28 AM
Wait, I could make it some easier. I forgot that AutoIt uses a UPX packer even when you choose zero compression. I can swap in a dummy UPX.exe to get around that. However, it is still an interpreted script packed inside the interpreter. So poor Olly will still think your on drugs. Anyway, here's one without the upx packer.

This piece of AutoIt script runs in the tray and give me copy access through Ctrl-x. Need a better title match though:
Code: [Select]
#include <IE.au3>
HotKeySet("^x","cpy")
Sleep(2147483647) ; No reason to run it longer than 24 days :)
Func cpy()
   $oIE = _IEAttach("MasmBasic", "embedded")
   If @error Then Return
   Local $sText = $oIE.document.selection.createRange().text
   If $sText="" Then Return
   ClipPut($sText)
EndFunc
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 05:46:35 AM
So poor Olly will still think your on drugs. Anyway, here's one without the upx packer.

Well, somehow ::)

P.S.: See Basil Yercin (http://www.movsd.com/board/index.php?topic=7890.msg57906#msg57906) on IID_IAccessible in Masm syntax. Looks horrific :biggrin:
Title: Re: Contextual help project
Post by: qWord on July 31, 2012, 07:30:16 AM
Hi,
you can solve the Copy&Paste problem by replacing CoInitialize(NULL) with OleInitialize(NULL) in the WinMain.
There is note about it here (http://msdn.microsoft.com/en-us/library/aa770041(VS.85).aspx).

EDIT: do not forget OleUninitialize()
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 07:32:59 AM
Nice, looks like qWord has found the easy solution while I was typing.

 ::) I just read about how that was put into later versions of AutoIt. Basically, because a compiled AutIt scipt is essentially the interpreter, which the EULA doesn't allow decompilation of, with a script packed inside of it they decided that decompilation of scripts with a debugger was essentially a decompilation of the interpreter. Apparently they have a back door available for AV companies. This was news to me before today. However, I have source code to earlier version of AutoIt (yes legally obtained, not reversed). I also have earlier AutoIt versions. I could try compiling with one of those earlier AutoIt versions if your really interested, but I would need to unpack them and do some experimenting and checking version histories for DllCall. Not sure how much good it would do. Even many of the APIs are wrapped in DllCall and implemented in script. I could also send you IE.au3 which implements the Dll calls.

This page has essentially a full implementation of what is relevant anyway:
http://files.codes-sources.com/fichier.aspx?id=52594&f=html%2Fhtml.asm
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 08:05:46 AM
Nice, looks like qWord has found the easy solution while I was typing.

Sometimes he is really useful 8)
Japheth reacted also (http://sourceforge.net/tracker/?func=detail&aid=3552054&group_id=255677&atid=1126895), with a new zip (http://www.japheth.de/Download/Samples/IEContainerSample.zip).

Quote
I have source code to earlier version of AutoIt (yes legally obtained, not reversed).

I guess we can stop here - although your ObjectFromLresult etc approach looks feasible in Masm, I add that as a second OleTest zipfile below :biggrin:

By the way:
invoke LresultFromObject, offset IID_IAccessible, 2, 3   ; is that a pointer to RIID, or RIID itself??

xHelp3107.zip contains the new version of xHelp, with Copy enabled, and lots of credits to mywan, ryan and qWord :t

To the proud owners of \masm32\help\WIN32.HLP: Type SendMessage, press TAB, then < and tell me if it works ;)
Title: Re: Contextual help project
Post by: Ryan on July 31, 2012, 09:51:05 AM
I was not able to do what I wanted to do.

I've been using COMView http://www.japheth.de/COMView.html (http://www.japheth.de/COMView.html) to look at the available functions within a file.  For some reason when I look at "Microsoft Internet Controls", I see the Document property but not the Selection or CreateRange that mywan indicated that we need for getting the selected text.
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 11:09:09 AM
I was not able to do what I wanted to do.

I've been using COMView http://www.japheth.de/COMView.html (http://www.japheth.de/COMView.html) to look at the available functions within a file.  For some reason when I look at "Microsoft Internet Controls", I see the Document property but not the Selection or CreateRange that mywan indicated that we need for getting the selected text.
COM is more like a messaging system between objects in other applications to expose methods to external programs. CreateRange is actually a method, not object, in Microsoft's version of JavaScript. JavaScript doesn't expose itself the way MS does theirs. So basically it was in effect JavaScript code, not AutoIt or asm code, that I was implementing. This is allowed because OLE provides the messaging for the methods to be called from external apps. Expecting to see it with COMView is a bit like expecting to see the internal variables defined by MSPaint while looking at notepad. COMView only tells you about the objects that will send the messages for you, not what messages you can send. That is determined by the application you send the message to.
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 11:20:55 AM
Ok, that was probably the most difficult issue and it turned out quiet trivial. That leaves some rather basic stuff. Perhaps it's time for a punch list, like when finishing up a construction project. I have one more easy one since my last set list. The list is very short at this point though  :t

1) Pass command line into the search box. Duh..
2) Activate the IEContainer, if open, when the search box is maximized (gains focus) or navigation occurs.

After starting to use xHelp a lot for my own study of MASM the need for 2) became obvious. It has already saved me lots of hours even unfinished. I often click xHelp on the taskbar to minimize/maximize it so it doesn't close the container or interfere with my text editor. Then when I do a new search the container navigates but remains under the other windows. Also activating the container when xHelp is activated is just a little extra convenience for when I keep switching back and forth between my editor and the same htm page. Icing would be if the container was also minimized whenever you minimize xHelp. Basically make them activate and deactivate in tandem for the most part.

I guess the easiest way to implement command line searches when xHelp was already open would be to have xHelp kill any prior instances of itself. There's less hackish ways to do it so that's up to you. Other than that you have an app usable enough I will not waste my time trying to reinvent it in the foreseeable future. Too many other things I also want to accomplish, and better suited to my skill level while still offering a learning experience.

Nice job, very little left to do  :bgrin:
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 05:36:49 PM
1) Pass command line into the search box. Duh..
2) Activate the IEContainer

OK, give it a try ;-)
Title: Re: Contextual help project
Post by: mywan on July 31, 2012, 07:56:30 PM
Near perfect  :t
I did forget 3)
3) Fix the <Win32.hlp>

That makes the the list:
1) Command line search.
2) <Win32.hlp>

Though mostly I'm not terribly worried about <Win32.hlp> at this point. You could just drop it without creating any significant inconvenience.
Title: Re: Contextual help project
Post by: jj2007 on July 31, 2012, 09:00:36 PM
I have added
\Masm32\help\xHelp\L_Command.exe
\Masm32\help\xHelp\L_string.exe

to the archive, for testing the launch via commandline. They use this simple source:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
   Init
   Launch "\Masm32\help\xHelp\xHelp.exe string array"
   Exit
end start

... but of course you could do the same from VB. Attention it's ANSI, not Unicode.
Once you see the new search string, you can use Return to display the first item, or TAB to move to the list; if the search is e.g. for CreateWindowEx, hit TAB, then < to see it right away in Win32.hlp

A propos: What's wrong with <Win32.hlp>? Works fine over here, as long as it is in \Masm32\help\WIN32.HLP ::)
Title: Re: Contextual help project
Post by: mywan on August 01, 2012, 11:07:25 AM
Oh, the command line does work from a command prompt, but doesn't work if I try to put the command in a shortcut. Hence I never even knew it had a command line search option.

Wait: I put a space in the path so windows would let me quote the app path string and it started working and continued working after I removed the space. Very very weird. I'm going to experiment to figure out what's happening. As far as I can tell L_Command.exe and L_string.exe does nothing at all with or without an arg or whether xHelp is running or not.

Anyway, I'm going to configure my editor to use xHelp through F1 and see how it goes.
Title: Re: Contextual help project
Post by: mywan on August 01, 2012, 01:23:18 PM
Apparently the command line issue was related to the "start in:" folder. If you have a path to execute like "\Desktop\xHelp\3107b\xHelp.exe blah" with a shortcut "start in:" path set to "\Desktop\xHelp\3107b\" with another xHelp in that "start in:" path then win 7 64 bit will execute that rather that the exe actually pointed to by the target string. Don't know about other systems. Well anyway...

I moved \xHelp under \masm where it was intended to be, and added this configuration string to my editor:
command.help.$(file.patterns.asm)=C:\masm32\help\xHelp\xHelp.exe $(CurrentWord)

This works perfectly, unless xHelp.exe is already running. If xHelp.exe is not running this runs xHelp.exe as hidden and it only show up in the task manager, and the fact that the editor never returned an exit code. So using my editor requires that Xhelp already be running. Apparently so long as Xhelp passes an arg it will never run a new instance. But xHelp running without an arg can run as many instances of xHelp as you want. A shortcut with args creates a new visible instance of xHelp fine, yet when executed from my editor it's hidden unless there was a preexisting instance of xHelp running. Almost certainly this is triggered by output redirection.

Code: [Select]
.if CL$() ; get the commandline
xchg eax, esi
.if Len(esi)>2
.if WinByTitle("Masm32 xHelp", 4)  ; we'll send a WM_COPYDATA message to
push eax ; arg for SetForegroundWindow
SendData eax, esi ; change the findbox in the current instance
call SetForegroundWindow
Exit
.endif
Let cLine=esi ; use to set hFind
.endif
.endif

Title: Re: Contextual help project
Post by: jj2007 on August 01, 2012, 06:07:42 PM
If you have a path to execute like "\Desktop"...
Is that desktop in the root??

Quote
This works perfectly, unless if xHelp.exe is already running - unless or if??.

Apparently so long as Xhelp passes an arg it will never run a new instance. But xHelp running without an arg can run as many instances of xHelp as you want.

That will be changed, it's bad behaviour indeed. Single instance is enough.
This part should have no problems with paths because it just sends a message:

Code: [Select]
.if CL$() ; get the commandline
xchg eax, esi
.if Len(esi)>2
.if WinByTitle("Masm32 xHelp", 4)  ; we'll send a WM_COPYDATA message to
push eax ; arg for SetForegroundWindow
SendData eax, esi ; change the findbox in the current instance
call SetForegroundWindow
Exit
.endif
Let cLine=esi ; use to set hFind
.endif
.endif

The only other potential problem with shortcuts is that xHelp.exe looks for IEContainer.exe in the current path. I could change that, though, by prepending the GetModulePathName, if you really need to launch it through a shortcut.

Edit: New version attached. It forces single instance and looks for IEContainer.exe in the same folder as xHelp.exe, e.g. \masm32\help\xHelp\xHelp.exe
In addition, if
- there is already an instance running
- a request for a string longer than 4 character with no spaces is sent
- no matches are found in the *.htm files
- and \masm32\help\xHelp\WIN32.HLP is present
then the string gets passed on directly to Win32 help.
Title: Re: Contextual help project
Post by: mywan on August 01, 2012, 09:50:45 PM
If you have a path to execute like "\Desktop"...
Is that desktop in the root??
I do quiet often unzip to the desktop to try it out.

Quote
This works perfectly, unless if xHelp.exe is already running - unless or if??.
Quote
Apparently so long as Xhelp passes an arg it will never run a new instance. But xHelp running without an arg can run as many instances of xHelp as you want.
I did in fact mean unless, not if.
If xHelp is already running then when my editor executes:
command.help.$(file.patterns.asm)=C:\masm32\help\xHelp\xHelp.exe $(CurrentWord)
It works fine.
If xHelp is not already running then when my editor runs it in hidden mode. The window is invisible, but it is running. The code selection below is not about separate instances, it about the fact that my editor redirects standard out back to itself is likely the cause of the issue. Hence when ShowLbSel > "invoke ShowWindow, lastWin, SW_HIDE" it's not the window you think your hiding. In this case lastWin is the current window.

Quote
That will be changed, it's bad behaviour indeed. Single instance is enough.
This part should have no problems with paths because it just sends a message:
Code: [Select]
.if CL$() ; get the commandline
xchg eax, esi
.if Len(esi)>2
.if WinByTitle("Masm32 xHelp", 4)  ; we'll send a WM_COPYDATA message to
push eax ; arg for SetForegroundWindow
SendData eax, esi ; change the findbox in the current instance
call SetForegroundWindow
Exit
.endif
Let cLine=esi ; use to set hFind
.endif
.endif
You completely missed the point when you presumed I meant "if" when I said "unless".

Quote
The only other potential problem with shortcuts is that xHelp.exe looks for IEContainer.exe in the current path. I could change that, though, by prepending the GetModulePathName, if you really need to launch it through a shortcut.
No, don't change that. That works perfectly.


Quote
Edit: New version attached. It forces single instance and looks for IEContainer.exe in the same folder as xHelp.exe, e.g. \masm32\help\xHelp\xHelp.exe
In addition, if
- there is already an instance running
- a request for a string longer than 4 character with no spaces is sent
- no matches are found in the *.htm files
- and \masm32\help\xHelp\WIN32.HLP is present
then the string gets passed on directly to Win32 help.

My editor still runs the last version with SW_HIDE set is still absolutely consistent. If strings longer than 4 characters with no spaces are redirected for any reason you'll trash my capacity to use any of the notes I've been compiling. If that happens the app becomes nearly useless to me. I did download Win32.hlp to see what it was you intended. I was way off on what I thought you were trying to do with <Win32.hlp>. Last time I seen that help file was in win 95 days, and I only have limited use for it personally. Though it is still effectively relevant info the only bits of information I need is not the definitions it contains but rather it's proper usage (syntax) in MASM.

xHelp01Aug.zip fixed none of the issues.
Title: Re: Contextual help project
Post by: jj2007 on August 02, 2012, 01:34:57 AM
Sorry that it doesn't work for you. In any case, thanks for the really detailed and well elaborated feedback. You have helped me a lot :icon14:

Can anybody else give feedback? It seems mywan's setup is a bit unusual - how does a standard installation (XP, Win7) work with xHelp version 1 August posted above?

Thanks,
jj
Title: Re: Contextual help project
Post by: mywan on August 02, 2012, 03:16:42 AM
Sorry that it doesn't work for you. In any case, thanks for the really detailed and well elaborated feedback. You have helped me a lot :icon14:

Can anybody else give feedback? It seems mywan's setup is a bit unusual - how does a standard installation (XP, Win7) work with xHelp version 1 August posted above?

Thanks,
jj
It doesn't take an unusual setup to reproduce the SW_HIDE bug. All it takes is run it with any program that pipes standard out from xHelp back to itself. Basically when run from any editor with an output pane. You can download a standalone SciTe setup and see it yourself. I can also write a quick program to demonstrate it if you wish.
Title: Re: Contextual help project
Post by: jj2007 on August 02, 2012, 06:05:11 AM
OK, I fixed one issue: xHelp.dat got a prepended path from GetModuleFileName, because when xHelp was launched from elsewhere, it couldn't find the settings in xHelp.dat - and that could indeed produce a half-hidden IE mini window in the upper left corner.

xHelp is tested with the MasmBasic (http://masm32.com/board/index.php?topic=94.0) editor (RichMasm), and there it works chained with the MasmBasic guide, i.e. it first tests if e.g. SendMessage is a MasmBasic command (it's not, of course), then passes the search string on to xHelp, which finds several matches in \masm32\help and, if the user wishes so, offers also Win32.hlp (still the best choice for many API calls because the SendMessage page pops right into your face). PostMessage would not have matches for \masm32\help\*.chm, so xHelp will show you directly the Win32.hlp page, except when launched the first time: then it displays the dialog, and you have to hit Return.

Re redirection, as said earlier it shouldn't be an issue because 1. why should an editor redirect the search string if none of the bloody M$ search products returns info on whether searching was successful and 2. xHelp does not use StdIn or StdOut, it's a plain Windows app.
 :icon14:
Title: Re: Contextual help project
Post by: mywan on August 02, 2012, 06:22:18 PM
When I run xHelp from SciTe and get an invisible instance of xHelp running I ran the following script to show its state:

Code: [Select]
Dim $str
Dim $state=WinGetState("[CLASS:MB GUI]","")
If BitAND($state,1) Then
   $str="Exist: True"&@CRLF
Else
   $str="Exist: False"&@CRLF
EndIf
If BitAND($state,2) Then
   $str=$str&"Visible: True"&@CRLF
Else
   $str=$str&"Visible: False"&@CRLF
EndIf
If BitAND($state,4) Then
   $str=$str&"Enabled: True"&@CRLF
Else
   $str=$str&"Enabled: False"&@CRLF
EndIf
If BitAND($state,8) Then
   $str=$str&"Active: True"&@CRLF
Else
   $str=$str&"Active: False"&@CRLF
EndIf
If BitAND($state,16) Then
   $str=$str&"Minimized: True"&@CRLF
Else
   $str=$str&"Minimized: False"&@CRLF
EndIf
If BitAND($state,32) Then
   $str=$str&"Maximized: True"&@CRLF
Else
   $str=$str&"Maximized: False"&@CRLF
EndIf
MsgBox(0,"xHelp Window States:",$str)

That produces this message box:
Title: Re: Contextual help project
Post by: jj2007 on August 02, 2012, 08:05:27 PM
OK, I found the bugger when launching it via SciTex. Weird things may happen when launched from there, but when I inserted a ShowWindow SW_SHOW before entering the message loop, everything seems just fine.

By the way, the buggy version worked e.g. for PostMessage, i.e. for a search that triggered the Win32 hlp window and therefore didn't need the main xHelp dialog.

Attached the new one, source included.

Again, thanks for all your efforts, mywan :icon14:
Title: Re: Contextual help project
Post by: mywan on August 03, 2012, 03:00:31 PM
Sorry, been a bit tied up lately. Yes, the issue is fixed. As far as I can tell atm there's nothing left to fix, except maybe a few nitpicks. Everything seems to be fully functional and working  :eusa_clap:
Title: Re: Contextual help project
Post by: jj2007 on August 03, 2012, 04:35:38 PM
Great :t

I have started a thread on how to use it in qEditor (http://masm32.com/board/index.php?topic=531.msg4192#msg4192). If anybody likes to add howtos for other editors, that would be most welcome. It's already tied to the F1 key in MasmBasic's RichMasm editor.
Title: Re: Contextual help project
Post by: jj2007 on August 04, 2012, 08:49:58 AM
I added one new feature: While scrolling through the html files in the listbox, you can press + (plus, like in "more") to see the original chm file in HtmlHelp. If you need this feature, extract xHelp.exe from the MasmBasic archive (http://masmforum.com/~masm32/board/index.php?topic=94).
Title: Re: Contextual help project
Post by: mywan on August 05, 2012, 04:28:48 AM
The + key seems to work quiet well also. I'll get around to playing with the MasmBasic library sometime also. Right now I'm just trying to gain some proficiency at dealing with various procedures using the basic instruction set. I still want to have some idea of what these libraries consist of before starting to depend on them too much.
Title: Re: Contextual help project
Post by: jj2007 on August 05, 2012, 06:59:46 AM
I still want to have some idea of what these libraries consist of before starting to depend on them too much.

That is not a trivial point, of course. There is kind of a hierarchy there:

- 68 00204000 (the x86 CPU knows what it is, be it on Windows or Linux or a Mac)
- push offset mystring + call StdOut (StdOut is part of the Masm32 library, it uses WriteFile, which is part of the Windows library)
- invoke StdOut, addr mystring (same but it uses the invoke feature of Microsoft Macro Assembler)
- print "Hello World" (the Masm32 library, you will depend on the goodwill of Hutch :P)
- Print "Hello World", CrLf$, "Today is the ", Date$ (the MasmBasic library, depends on the Masm32 installation, on Windows, and on the goodwill of jj)

You need growing levels of confidence to use each of these features ;)
As the author, I have full confidence in MB; but I still designed it in a way that I can use it in parallel to Masm32 code, and with ML (6.15...9.0) and JWasm. Most if not all of the code in \masm32\examples works just fine if you replace the whole .model, .586, include whatever stuff with one single line, include \masm32\MasmBasic\MasmBasic.inc
I see MB as "inline Basic", in analogy to "inline assembler" in C code. Its main advantage is a productivity gain from not having to repeat boring stuff all the time:

   Let esi=FileRead$("MyCrFile.txt")
   push esi
   .Repeat
      lodsb
      .if al==13
         mov byte ptr [esi-1], 10
      .endif
   .Until !al
   pop esi
   FileWrite "MyLfFile.txt", esi

Masm32 can do almost the same in a few steps more, but MB is designed to do the trivial file I/O and string manipulation etc stuff easily and fast, and that's how I mostly use it. My bigger sources are nowadays about 10% MasmBasic and 90% "true" assembler. But those 10%, if expanded to "true" assembler, would eat a disproportionate amount of my mental resources.

Here in the forum, you will find a fair share of "purist macro haters" and an equally fair share of pragmatic programmers who do not feel ashamed to show a print "hello world" instead of the real stuff. It's an ideologic debate, sometimes a religious one, but try to get a feeling which side is more productive :biggrin:
Title: Re: Contextual help project
Post by: mywan on August 05, 2012, 12:25:26 PM
I'm not entirely a purist when it comes to code conventions. I am a purist in the sense that I want to know the cost/benefit ratio as well as the underlying mechanics of the pure assembly when I use these libraries. So even when these macros come at effectively no machine cost and significant ease of use I still want to know what makes them tick. I don't even need to be especially proficient at straight assembly versions of those macros, as long as I can fully comprehend what the purist versions entail.

Basic string handling is what I'm experimenting with the most at the moment. One of my near term goals is to write an ini file parser. The string macros that operate by modifying existing strings is a very nice and powerful feature but also gets in the way sometimes. I also still have various types of arrays to experiment with implementing, dynamic buffer allocations, etc. I have got switch and select type constructs down very nicely in pure asm, without macros. I love the level of fine tuned control I have with these that higher level languages often don't provide.

My first operational assembly programs will be a small app (Browser.exe), that I believe I presently have sufficient skills to implement all the primary functionality of. It will drop itself into the same folder as either Firefox.exe or chrome.exe and copy all profile data from %appdata%\<sunbdirectory> to a profile subdirectory under Browser.exe such that your existing Firefox/Chrome installation, settings, addons, etc., becomes a standalone application. At that point you can merely copy or move your Firefox/Chrome folder from 'Program Files' to any USB, removable drive, or just a different location on the same drive. Then it can run from anywhere or any computer, with all the same settings, bookmarks, plugins. etc., and also act as a profile manager replacement. No tracks, cache, registry entries, etc., would be left on any machine it was run on. Except maybe supercookies, depending on settings, through flash and silverlight. I may include a mechanism to clean that up also, through caching the original state. It can also be used to back up and restore any existing Firefox/Chrome installation and settings without needing a new installation. My computer no longer even has a default browser, but rather defaults to a browser/source editor/settings selection menu. The one I'm working up to is a rewrite of my Drawer.exe app in assembly. For this I will likely make good use of your macro library :icon_mrgreen:

Title: Re: Contextual help project
Post by: jj2007 on August 05, 2012, 04:11:44 PM
One of my near term goals is to write an ini file parser.

Here is one, written in less than ten minutes between fully waking up and having my first coffee ;-)

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
  Init
  Recall "\Masm32\menus.ini", qEdMenu$()

; put you resource editor here
; -----------------------------
; &Microsoft Image Editor,\MASM32\BIN\Imagedit.exe

  push eax
  xor ebx, ebx
  Let edi="Editors used in your qEditor installation:"
  .Repeat
   mov esi, qEdMenu$(ebx)
   .if Instr_(esi, "edit", 1)
      .if Instr_(esi, ".exe", 1)
         Let edi=edi+CrLf$+Replace$(Left$(esi, Rinstr(esi, ",")-1), "&", "")
      .endif
   .endif
   inc ebx
  .Until ebx>stack
  pop eax
  Inkey edi
  Exit
end start

Keep me posted :t
Title: Re: Contextual help project
Post by: mywan on August 06, 2012, 06:10:14 PM
Got side tracked momentarily on some EPR related algorithms (EPR paradox). Can't let crazy ideas go untested.

I'm not recognizing how your code snippet above is structured, or even what the majority of keywords refer to.
I see Recall in MasmBasic.inc but not making much from it either.
Can't find any other reference to the qEdMenu$ function.
Let looks incredibly useful from what I can make from MbGuide.rtf, but I'm very short on details. The rich text is also very difficult for me to parse, due to extreme variations in text sizes and limited display width.
With Rinstr again I am forced to look through cross-branched trees of unfamiliar macros to try to figure out what the initial macro actually does. Can only guess from context.
I also don't know what the relavance of "Editors used in your qEditor installation:" was. It didn't appear to be associated with the content of menus.ini. PushString (from MasmBasic.inc) seems like it's closely related to Let.

Anyway, trying to work through even that short code snippet blocked me at almost every turn while trying to work out the details of the logical flow. Some of those macros you use look like something I would have a difficult time living without, but at present I need to learn a lot of basics and include new macros piecemeal, one by one, as I gain better incite into their details.

I'm particularly interested in the Let macro atm. From what I gather it looks like something that is well suited for present issues I am working out. Recall also looks interesting. Where is the best place to get basic descriptions of these macros without the issues described?
-----
Noticed something about xhelp. When I search "instr" the only find is from REP.htm in opcodes.chm. Yet a search for "instring" returned 3 hits from masmlib.chm. Makes fishing for useful unknown macros, based on guesses, and such a bit more difficult. Full strings searches are understandable but this isn't always the case, like: "GetFiles" finds "GetFileSize()" in hlhelp.chm::/fsize.htm.
Title: Re: Contextual help project
Post by: jj2007 on August 06, 2012, 06:45:28 PM
I'm not recognizing how your code snippet above is structured, or even what the majority of keywords refer to.
I see Recall in MasmBasic.inc but not making much from it either.
Can't find any other reference to the qEdMenu$ function.
...
I'm particularly interested in the Let macro atm. From what I gather it looks like something that is well suited for present issues I am working out. Recall also looks interesting. Where is the best place to get basic descriptions of these macros without the issues described?
-----
Noticed something about xhelp. When I search "instr" the only find is from REP.htm in opcodes.chm. Yet a search for "instring" returned 3 hits from masmlib.chm. Makes fishing for useful unknown macros, based on guesses, and such a bit more difficult. Full strings searches are understandable but this isn't always the case, like: "GetFiles" finds "GetFileSize()" in hlhelp.chm::/fsize.htm.

Thanks for the feedback. It seems I simply assume too much :redface:
Recall translates a file from disk into a string array; qEdMenu$ is not function but rather the array created by Recall. You could use Print qEdMenu$(1), for example, or use it both ways in Let statements:

Let esi="String1=["+qEdMenu$(1)+"]"
Let qEdMenu$(0)="I decided to change the first array element"

Instr_ and Rinstr are BASIC keywords that find matches in strings, where the "R" stands for "from the right end of the string".

HTH - right now I have little time to write, but MbGuide.rtf is a good source, as well as the MasmBasic Quick Reference (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm)
Title: Re: Contextual help project
Post by: mywan on August 06, 2012, 08:24:35 PM
MasmBasicQuickReference seems to be a good start on what I need but leaves a lot to be desired. Looking at some of the string handling there it looks functionally quiet similar to functions I am quiet familiar with, just with differing syntax and details.

Your assumptions are understandable and a necessary part of being proficient. We all make similar presumptions in areas we understand, and it's not always easy to recognize just how many we make. Neither is it your job to hold my hand through this kind of stuff. I'll handle my own deficiencies to my own satisfaction in time. I appreciate what you can offer though :bgrin:

My string handling is still just a bunch of experimental attempts chopping and splicing strings where I can watch each step of what happens to different strings. One thing I still fall short on is efficient methods of buffering the string segments I want to store for later use. Haven't even got to arrays yet. Below is a couple of code snippets I wrote that I find to be the simplest and easiest to fully comprehend. All the rest of the code I've personally written with asm is just experimental snippets to see the output. Yes, highly limited experience here with assembly, but I have a fairly well defined sequence of practice problems (geared to my needs) to get better.

This sets the parameters to create a window with the bottom left corner at the mouse, and restricts the window inside the top and right of the screen (working code).
Code: [Select]
invoke GetCursorPos,addr pt
mov WinH,300
mov WinW,200
mov DskX,FUNC(GetSystemMetrics,SM_CXSCREEN)
mov DskY,FUNC(GetSystemMetrics,SM_CYSCREEN)
mov eax,pt.x
add eax,WinW
cmp DskX,eax
jg short pWinX
mov eax,DskX
sub eax,WinW
mov pt.x,eax
pWinX: mov eax,pt.y
sub eax,WinH
cmp eax,0
jg short pWinY
mov eax,WinH
mov pt.y,eax
pWinY: mov eax,WinH
sub pt.y,eax

Later on WinW and WinH will be defined as a multiple of the number of entries to display from a config file.

This is the most compact and comprehensible working WndProc I've written. It's far simpler and makes much more sense to me than nested .If statements I replaced. Still has a few comment lines from me playing with various stuff. Not sure why the endprc: is need, except maybe caution, but it seems to be part of all the samples I see.

Code: [Select]
WndProc PROC hwnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
cmp wParam,VK_ESCAPE
jne @F
invoke DestroyWindow,hWnd
jmp EnSw
@@: cmp wParam,VK_F1
jne @F
;mov MyArgs,len(rv(GetCommandLine))
;invoke ShellExecute,0,chr$("open"),CmdLine,NULL,NULL,SW_SHOW
;MsgBox hWnd, CmdArgs,"Command",MB_OK
jmp EnSw
@@: cmp uMsg,WM_ACTIVATEAPP
jne @F
cmp wParam,0
jne @F
invoke DestroyWindow,hWnd
jmp short EnSw
@@: cmp uMsg,WM_DESTROY
jne @F
invoke PostQuitMessage,0
jmp EnSw
@@: cmp uMsg,WM_LBUTTONDOWN
jne EnSw
MsgBox hWnd, "lpReturnedString","Command",MB_OK
EnSw: invoke DefWindowProc,hwnd,uMsg,wParam,lParam
ret
endprc: xor eax, eax
ret
WndProc ENDP
Title: Re: Contextual help project
Post by: jj2007 on August 06, 2012, 11:18:58 PM
MasmBasicQuickReference seems to be a good start on what I need but leaves a lot to be desired.
I know ;-)

Quote
This is the most compact and comprehensible working WndProc I've written. It's far simpler and makes much more sense to me than nested .If statements I replaced. Still has a few comment lines from me playing with various stuff. Not sure why the endprc: is need, except maybe caution, but it seems to be part of all the samples I see.

Code: [Select]
WndProc PROC hwnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
cmp wParam,VK_ESCAPE
jne @F
invoke DestroyWindow,hWnd
jmp EnSw
@@: cmp wParam,VK_F1
jne @F
;mov MyArgs,len(rv(GetCommandLine))
;invoke ShellExecute,0,chr$("open"),CmdLine,NULL,NULL,SW_SHOW
;MsgBox hWnd, CmdArgs,"Command",MB_OK
jmp EnSw
@@: cmp uMsg,WM_ACTIVATEAPP
jne @F
cmp wParam,0
jne @F
invoke DestroyWindow,hWnd
jmp short EnSw
@@: cmp uMsg,WM_DESTROY
jne @F
invoke PostQuitMessage,0
jmp EnSw
@@: cmp uMsg,WM_LBUTTONDOWN
jne EnSw
MsgBox hWnd, "lpReturnedString","Command",MB_OK
EnSw: invoke DefWindowProc,hwnd,uMsg,wParam,lParam
ret
endprc: xor eax, eax
ret
WndProc ENDP

Caution: There are many Windows messages around, and some could have VK_ESCAPE or VK_F1 in their wParams with an entirely different meaning. The correct and safe way is to check for the uMsg first:
Code: [Select]
WndProc PROC hwnd:DWORD,uMsg:DWORD,wParam:DWORD,lParam:DWORD
SWITCH uMsg
CASE WM_KEYUP
cmp wParam,VK_ESCAPE
jne @F
MsgBox hWnd, "Esc","Command",MB_OK
invoke DestroyWindow,hWnd
jmp EnSw
@@: cmp wParam,VK_F1
jne @F
MsgBox hWnd, "F1","Command",MB_OK
jmp EnSw
CASE WM_CREATE
...
ENDSW

Title: Re: Contextual help project
Post by: mywan on August 07, 2012, 12:43:25 AM
Thanks for the heads up, I'll fix that. However, if you will notice the window exits if it merely loses focus via WM_ACTIVATEAPP.

http://msdn.microsoft.com/en-us/library/windows/desktop/ms632614%28v=vs.85%29.aspx
Quote
Sent when a window belonging to a different application than the active window is about to be activated. The message is sent to the application whose window is being activated and to the application whose window is being deactivated.

This is by design as the window is there to simply make a choice, and automatically go away if the user either makes that choice or decides to do something else entirely. The worst it could do is accidentally make the window do what it was supposed to.
Title: Re: Contextual help project
Post by: jj2007 on August 07, 2012, 02:23:37 AM
you will notice the window exits if it merely loses focus via WM_ACTIVATEAPP

That part was ok anyway, because you checked uMsg. Interesting idea, by the way - your users like it? I suppose the first two, three times, they might be a bit surprised not to find the window any more :biggrin:
Title: Re: Contextual help project
Post by: jj2007 on August 07, 2012, 03:48:49 AM
My string handling is still just a bunch of experimental attempts chopping and splicing strings where I can watch each step of what happens to different strings.

You might use the deb (http://www.webalice.it/jj2006/MasmBasicQuickReference.htm#Mb1017) macro, it is excellent for such testing:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
.data
lpBuffer   dd Buffer
Buffer   db 1000 dup(?)

   Init
   mov ebx, 3
   .Repeat
      mov lpBuffer, cat$(lpBuffer, chr$("test "))   ; Masm32 library
      deb 4, "Loop", ebx, $lpBuffer   ; prefix $ means "show the string content"
      dec ebx
   .Until Zero?
   Inkey "ok"
   Exit
end start

Quote
One thing I still fall short on is efficient methods of buffering the string segments I want to store for later use.

MasmBasic uses a circular buffer for producing e.g.

   Print "Today is the ", Date$, ", ", Time$, Str$(", and your mouse is at position X=%i and Y=", MouseX), Str$(MouseY), CrLf$

Note the two Str$() - not so easy with Masm32 str$() ;)

deb comes with an integer:
  deb 1, "1,2,3 means show in a MsgBox", eax
  deb 4, "Four means show in console window", eax, Xmm0, ST(1), $esi
  deb 5, "Five means write to logfile", eax, $esi
  deb 6, "Six and higher means show the first n results", ebx, $lpBuffer

Test this with the example above:
   mov ebx, 200
   .Repeat
      mov lpBuffer, cat$(lpBuffer, chr$("test "))   ; Masm32 library
      deb 6, "Loop", ebx, $lpBuffer   ; prefix $ means "show the string content"
      dec ebx
   .Until Zero?

The MsgBoxes of deb 1/2/3 can be cancelled independently, so that you can debug several loops in one go.



Just for fun, here an example how a Split$() macro could be implemented:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)

Split$ MACRO src, array, delimiter:=<" ">   ; splits strings using a delimiter, by default: a space
  StringToArray Replace$(src, delimiter, CrLf$), array
ENDM

   Init

splitcode_s:
   Split$ "This is a test for Split$()", MySplit$()   ; create the string array MySplit$() using spaces as delimiter
   ; Split$ "This@_#is@_#a@_#test@_#for@_#Split$()", MySplit$(), "@_#"   ; why simple if you can complicate things ;-)
splitcode_endp:
   push eax

   xor ecx, ecx
   PrintLine 'Result of splitting the string "This is a test for Split$()":'
   .Repeat
      Print Str$("\nString %i\t", ecx), MySplit$(ecx)
      inc ecx
   .Until ecx>=stack

   pop eax
   Print String$(5, CrLf$)
   CodeSize splitcode   ; 58 bytes needed for using Split$()
   Inkey
   Exit
end start

P.S.:
   Split$ Cat$(FileRead$("\Masm32\include\Windows.inc")), MySplit$(), CrLf$   ; works fine but is slow - about 10 ms on my Celeron M
   Recall "\Masm32\include\Windows.inc", MySplit$()   ; Recall is much faster, less than 3 ms; however, you cannot use Recall for merging two files to an array, as shown below:

   Split$ Cat$(FileRead$("\Masm32\include\Windows.inc")+FileRead$("\Masm32\include\WinExtra.inc")), MySplit$(), CrLf$
   Store "WinBoth.inc", MySplit$()   ; test the result
Title: Re: Contextual help project
Post by: mywan on August 07, 2012, 03:09:02 PM
I really do need to experiment with your macros. One of my quandaries was how to best go about creating something similar to a circular buffer, to hold various string segments associated with my Drawer app. I have got to the point where I can chop the strings into the parts I need, but I haven't dealt with 'efficient' persistent buffer storage for them yet. Neither have I dealt with retrieving the initial strings from a configuration file yet. As you noted, the Str$() functions are not so straight forward in Masm32 as you make it look. The ones that operate by modifying the existing string is very cool, but sometimes not well suited in some circumstances.

I would still prefer addons like MasmBasic (http://masm32.com/board/index.php?topic=94.0) to be more modular in its approach, at least while I'm on such a steep learning curve.

That part was ok anyway, because you checked uMsg. Interesting idea, by the way - your users like it? I suppose the first two, three times, they might be a bit surprised not to find the window any more :biggrin:
Everybody that has used it so far, though that number is limited, prefers it over anything else they have seen. The only version I have is an AutoIt script version written primarily as just a proof of concept demonstration. Even so, it turned out to be more than sufficient for me to go ahead and replace all my windows file association with it.

Those code snippets is the beginnings of the asm rewrite for Drawer.exe. The only surprise would be if the choice made failed. Basically if you double click a file type associated with the Drawer, like Drawer.asm, it provides a set of choices such as "Edit with Qeditor", "Edit With SciTe", "BuildAll (Console)", "BuildAll (Window)", "Execute", etc. As many options as the user wishes to include. If this is called from a source editor it can be instructed to pipe output back to that editor, even through a daisy chain of Drawers. If it's opened as a Drawer, such as a shortcut on the Quick Launch bar, it passes a user defines argument to identify which Drawer of options/apps to display. For instance, I have an "Internet" Drawer that contains all my browsers, Internet connection settings, etc., and can also include options to open different user profiles with the same browser. This Choose and die or die approach, like a context menu or start menu, means the Drawers are effectively reentrant, so choices can be cascaded like subfolders of choices without losing track of the reference file or drawer which initiated the cascade. In practice tracking the initial object is not usually required, and merely involves selecting a new Drawer like "Internet Settings" opening a new Drawer of options from the "Internet" Drawer.

This basically means I have literally hundreds of apps 2 clicks away from my Quick Launch bar with only a handful of icons and no need of a start menu. It basically puts a start menu on steroids on every icon on the quick launch bar. Really cool in Linux also with a minor addition of Linux file type support. Though the Xdesktop developers royally screwed Linux, especially given that this is how Linux is designed at the core to operate. Nobody is surprised when the start menu closes after a choice or no choice. Same here. The same Drawer.exe is shelled to from all my source code editors, with output piped back to the editor, for compile/edit/run/etc. options. Since this Drawer is also associated with every file type on my machine a separate drawer is defined for each file type. Even executables and folders have their own drawer configurations.

There is no background process or configurations outside the app folder, so it can be fully demonstrated (including Quick Launch) without making any changes to a machine that can't be undone simply by closing the new toolbar and deleting a shortcut in the "%APPDATA%\Microsoft\Windows\SendTo" folder. Unless of course you decide to make it the default open with for everything, or some subset of file types. SendTo is only useful for demonstrations to avoid system config changes.

That is my primary target to accomplish with assembly, though there are a few others targets in the interim. When I am proficient enough to rewrite my Drawer app in assembly I'll pretty much have the full range of skills I need for my personal needs.
Title: Re: Contextual help project
Post by: jj2007 on August 07, 2012, 05:27:03 PM
I really do need to experiment with your macros. One of my quandaries was how to best go about creating something similar to a circular buffer, to hold various string segments associated with my Drawer app. ... I would still prefer addons like MasmBasic (http://masm32.com/board/index.php?topic=94.0) to be more modular in its approach, at least while I'm on such a steep learning curve.

Perhaps you simply stick to a string array? The Recall/Store pair is designed to do that, see example below (source is attached).

Re modular: What exactly do you mean? As it stands, you replace one line at the top of your file with another one:
include \masm32\include\masm32rt.inc
include \masm32\MasmBasic\MasmBasic.inc
... and you start adding the bits and pieces you need. You are free not to use any of the MB "modules" - most sources in \Masm32\examples do not complain if you replace the model etc and include headers with that magic line. Often, I do that with other members' code for exactly one purpose: to use the deb macro when debugging the code (Olly is a brilliant tool, but for most purposes a deb 4 does the job, too).

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
   Init
   Recall "Drawer.ini", dri$()   ; create the dri$ array from a disk file
   push eax   ; eax is string count

   xor ecx, ecx
   Print "The old file:"
   .Repeat
      Print Str$("\nLine %i\t", ecx), dri$(ecx)
      inc ecx
   .Until ecx>=stack

   ; do useful things - freely invented:
   mov esi, Chr$("asm", 9)   ; we delete this one
   or ecx, -1   ; same as mov ecx, -1 but shorter
   .Repeat
      inc ecx
   .Until ecx>=stack || Instr_(dri$(ecx), esi)
   Delete dri$(ecx)   ; delete the asm file association string
   dec ecx
   .Repeat   ; replacing would be much easier than delete+append ;-)
      inc ecx
   .Until ecx>=stack || Len(dri$(ecx))==0
   Let dri$(ecx)="asm"+Tb$+"C:\Masm32\RichMasm\RichMasm.exe"   ; append a new one
   Store "DrawerNew.ini", dri$()   ; save your work to disk

   Inkey CrLf$, CrLf$, "The new file:", CrLf$, FileRead$("DrawerNew.ini")
   pop eax
   Exit
end start
Title: Re: Contextual help project
Post by: mywan on August 09, 2012, 05:59:51 AM
The modularity issue is more about easing my capacity to deconstruct the internal logic of the macros than it is about to what degree I choose to make use of them. As such it's really my responsibility to deal with, not your responsibility to 'fix' in some way. That fact would make going over the details of what I personally would prefer, to soften my learning curve, a moot issue.

I will definitely get to the point of deconstructing the logic of your code snippets, though it might take me some time. I have learned a lot from you, even if my comprehension remains somewhat limited at the moment. The easiest stuff for me to fully understand are the core directives, and I'll have to work out from there.

Title: Re: Contextual help project
Post by: jj2007 on August 11, 2012, 08:15:01 AM
I have updated xHelp in the MasmBasic package (http://masm32.com/board/index.php?topic=94.msg264#msg264). The source (xHelp.asc) is also included.
The only major change is under the hood:

      mov esi, Files$(ecx)
      Let HH$(ecx)=FileRead$(esi)   ; read the full content of e.g. \Masm32\help\xHelp\MASM_Programmers_Guide\Chap_04.htm
      ...
      Let HH$(ecx)=NoTag$(HH$(ecx))

The NoTag$ macro strips a string from all HTML tags. With the old xHelp, typing body would result in many matches - guess why :P
Title: Re: Contextual help project
Post by: mywan on August 11, 2012, 04:09:15 PM
The NoTag$ macro strips a string from all HTML tags. With the old xHelp, typing body would result in many matches - guess why :P
:lol:
I'll check out the new version after I get some sleep. Sounds like it may have addressed the last issue I described though.
Title: Re: Contextual help project
Post by: jj2007 on August 11, 2012, 05:53:43 PM
The NoTag$() gave me some headaches, but it's working now. This page can be translated as shown below with just a few lines:

include \masm32\MasmBasic\MasmBasic.inc   ; download (http://masm32.com/board/index.php?topic=94.0)
   Init
   Inkey NoTag$(FileRead$("http://masm32.com/board/index.php?topic=463.msg4552"))
   Exit
end start

Output (shortened, my colouring):
(....)Topic: Contextual help project (Read 1104 times) mywan Member Posts: 121
Re: Contextual help project « Reply #105 on: Today at 08:09:15 AM » Quote Quote from: jj2007 on Today at 12:15:01 AM The NoTag$ macro strips a string from all HTML tags. With the old xHelp, typing body would result in many matches - guess why

I' ll check out the new version after I get some sleep. Sounds like it may have addressed the last issue I described though. Logged
Reply
Unnotify
Mark unread
Print Pages: 1 ... 6 7 [ 8 ] « previous next »
The MASM Forum »

NoTag$() has its limitations, e.g. no text from document.write inside scripts etc, but for quickly extracting text content from HTML pages it serves its purpose.
Title: xHelp with SDK translation
Post by: jj2007 on August 18, 2012, 09:28:13 AM
Attached a BETA (!!) of xHelp that searches not only in the various *.chm files but also in the Windows SDK *.h files, e.g. in %ProgramFiles%\Microsoft SDKs\Windows\v7.0A\Include\*.h

After extraction to the root of the Masm32 drive, have a look at \masm32\help\xHelp\xHelp.ini and change the path if needed.

The main idea here is that \masm32\include\windows.inc can never be as complete as the official SDK header files - so why not go there and look up the exotic structure?

Feedback welcome, of course. The handling could be improved, I guess :biggrin:
Arrow left/right switches between listboxes, tab switches between main listbox and findbox.
Title: Re: Contextual help project
Post by: mywan on August 18, 2012, 10:17:46 AM
I don't use Windows SDK, nor intend to, so testing this is not really an option for me. I understand windows APIs in a structural sense, so I don't need help files, or to remember specifics, to find what I'm looking for. Would like to learn asm in pretty much the same way...