FpDebug breakpoint on "begin" lazarus / 12-Debugger ---------------------------------------------------------------------- 440bx · 2024-04-19 19:46 Hello, Please refer to the attachment.  FpDebug considers a breakpoint placed on a "begin" statement to be invalid.  This is unexpected, I believe a "begin" should be a valid "break" location. Also, in the breakpoints list (on the right), the little breakpoint bitmap is a little chopped. ---------------------------------------------------------------------- 440bx · 2024-04-19 20:10 Hello, This is not exactly an FpDebug thing but maybe FpDebug can mitigate the problem.  Please refer to the attachment. In the attachment there is a breakpoint on line 3318 (dc := BeginPaint(...)) but the breakpoint is completely obscured by the Hint about "ps does not seem to be initialized". At first sight it seems there is enough space to put the red breakpoint dot to the left of the little note bitmap.  Basically, if FpDebug could place its breakpoint indicator flush left there would be two (2) visible bitmaps at that location instead of just one. Another possibility that does not entail moving the breakpoint indicator is to place the breakpoint indicator on top of of the Hint indicator (instead of having the Hint indicator on top as it is now.)  Personally, I think the breakpoint is a lot more important than the Hint. ---------------------------------------------------------------------- Martin_fr · 2024-04-19 20:50 The 2 icons being drawn in the same column is entirely an issue in the IDE (either SynEdit, or somewhere SourceEditor). Please report an issue (not fpdebug related) that the editor unnecessarily overlaps gutter icons. Breakpoint on "begin" => I assume when you remove the breakpoint, then there is no blue dot on that line?  So the issue is that FPC does not generate code for that line. Btw, with -O1 that can even happen for lines containing break or exit statements. The reason why this works in gdb is, that gdb when given a line number will set the breakpoint at the next linenumber that has code (and stops at that next line...). GDB does that even if it is 1000 lines below. The curious I can't find the breakpoint, but it stops on the first line of the first routine in the unit => because the breakpoint is on line 1 "unit foo;" so the next line with code... Eventually FpDebug should have some smart way.... - a limit how many lines to look down - determining if it is within the same function (though that will not work for the first line of a function) For now, it has to be a line with code (actual asm statements attributed to the pascal statement on that line) in it (blue dot). ---------------------------------------------------------------------- Martin_fr · 2024-04-19 20:57 Talking about begin statements (and end)... The "begin" of a procedure/function has code, the so called "prologue" => in this code the stack frame (storage for locals) is set up. So when paused on that line, locals (and params) contain trash. Fpc currently does not mark this line as epilogue (though fpdebug is missing the interpretation of this mark too, but given its absence...). So the debugger gives no notice that those values are not yet initialized. Some versions of gdb detect "popular prologue asm", and internally stop only after the prologue., when the begin line is 99% done. Then the values are correct, but you aren't really a the start of "begin". ---------------------------------------------------------------------- 440bx · 2024-04-19 21:28 Quote from: Martin_fr on April 19, 2024, 10:50:39 pmPlease report an issue (not fpdebug related) that the editor unnecessarily overlaps gutter icons. Done.  Issue: 40914 link: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40914 Quote from: Martin_fr on April 19, 2024, 10:50:39 pmBreakpoint on "begin" => I assume when you remove the breakpoint, then there is no blue dot on that line?    So the issue is that FPC does not generate code for that line. You're right.  There is no blue dot on the line. Quote from: Martin_fr on April 19, 2024, 10:50:39 pmThe reason why this works in gdb is, that gdb when given a line number will set the breakpoint at the next linenumber that has code (and stops at that next line...). That's quite handy in the case of a breakpoint placed on a "begin". Quote from: Martin_fr on April 19, 2024, 10:50:39 pmGDB does that even if it is 1000 lines below. I think that's way too many lines below.  IMO, if the line is not visible in the current editor window then it shouldn't be set.  That way there are no "surprise breakpoints". Quote from: Martin_fr on April 19, 2024, 10:50:39 pmEventually FpDebug should have some smart way.... - a limit how many lines to look down - determining if it is within the same function (though that will not work for the first line of a function) For now, it has to be a line with code (actual asm statements attributed to the pascal statement on that line) in it (blue dot). Actually, if possible, I think placing a breakpoint on a non-code line should be limited to the breakpoint being placed on a "begin" line.  In most cases, there will be a statement soon after the "begin".  The only thing that is a potential "gotcha" is a "begin end" function/procedure.  I suppose in that case the breakpoint can go on the "end" line (FPC does seem to put a blue dot for those lines.) ---------------------------------------------------------------------- Martin_fr · 2024-04-19 22:04 It isn't that easy... of course not... There are 2 possible approaches to solve it. 1) In the editor, based on knowledge the editor has 2) In the debugger, based on knowledge the debugger has Well, mixes may be thinkable, but they are included... 1)  Editor. The breakpoint can get set, at a time at which the debugger is not yet running, the editor does not have any info if that line will or will not get a blue dot. - It would require an exchange when the debugger gets started. - Breakpoints can exist in units currently not open in an editor. For those blue dots aren't loaded (and storage is bound to the editor). So that is quite some extension. And it must all go through a generic interface that allows any backend to be bound to the IDE. Given IFDEF and include files and macros and whatnot, finding the kind of line, and the owning procedure and all that will also need a deep dive into code tools. Though that could be omitted, just limiting it to "simple" cases. 2) The debugger It doesn't have any source. It has to get it from the editor. But then the debugger would not go to codetools, it is not the job of the debugger to go parsing sources. What I thing should happen 1) Very simple: Allow n lines below (n between 1 and 5 / maybe configurable) But that could mean it goes into a different procedure. (if an "end" line has no code) 2) When the debugger can't find line 100 - search for the next known line above, get the function name from the dwarf - search for the next known line below, get the function name from the dwarf - if both surrounding lines are in the same function => then use the "next known line below" (as already found). That can still be limited by "up to max n lines". The only disadvantage => it does not work, if the breakpoint is above the first known line of a function. E.g on the "procedure foo;" line itself. Maybe the debugger can still see that the next found line is the first of the procedure, and take it if within a limit X (where X can be less or equal than the previous limit n) That is - "relatively simple" - works for most cases - can be done in the backend without interaction to the frontend Backend and frontend both. If sources are edited, the line movement is tracked "in the blue dots". Lines without them don't know if they moved. So adding a breakpoint there after editing will always be problematic. (That needs separate changes to the tracking...) In the meantime, it might be possible to allow for "ONE line beneath". That does only solve a subset of the issue, but it can't go very wrong either. ---------------------------------------------------------------------- Martin_fr · 2024-04-19 22:10 Not tested, but this patch should hopefully do the "one line" (and if you can spot the "1", you can make it more) Code: Diff  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i diff --git a/components/fpdebug/fpdbgclasses.pp b/components/fpdebug/fpdbgclasses.ppindex 2008434e26..e4b28951a8 100644--- a/components/fpdebug/fpdbgclasses.pp+++ b/components/fpdebug/fpdbgclasses.pp@@ -739,7 +739,7 @@   TDbgInstance = class(TObject)     function GetOSDbgClasses: TOSDbgClasses;     function GetPointerSize: Integer; -    function  GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean;+    function  GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray; AMaxFindLineBelow: integer = 0): Boolean;     function FindProcSymbol(const AName: String; AIgnoreCase: Boolean = False): TFpSymbol; overload;     function FindProcSymbol(AAdress: TDbgPtr): TFpSymbol; overload;   protected@@ -941,7 +941,7 @@   TDbgProcess = class(TDbgInstance)     function  FindSymbolScope(AThreadId, AStackFrame: Integer): TFpDbgSymbolScope;     function  FindProcStartEndPC(const AAdress: TDbgPtr; out AStartPC, AEndPC: TDBGPtr): boolean; -    function  GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance = nil): Boolean;+    function  GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance = nil; AMaxFindLineBelow: integer = 0): Boolean;     //function  ContextFromProc(AThreadId, AStackFrame: Integer; AProcSym: TFpSymbol): TFpDbgLocationContext; inline; deprecated 'use TFpDbgSimpleLocationContext.Create';     function  GetLib(const AHandle: THandle; out ALib: TDbgLibrary): Boolean;     property  LibMap: TLibraryMap read FLibMap;@@ -2198,12 +2198,20 @@ destructor TDbgInstance.Destroy;   inherited; end; -function TDbgInstance.GetLineAddresses(AFileName: String; ALine: Cardinal; var AResultList: TDBGPtrArray): Boolean;+function TDbgInstance.GetLineAddresses(AFileName: String; ALine: Cardinal;+  var AResultList: TDBGPtrArray; AMaxFindLineBelow: integer): Boolean; var   FoundLine: Integer; begin-  if Assigned(DbgInfo) and DbgInfo.HasInfo then-    Result := DbgInfo.GetLineAddresses(AFileName, ALine, AResultList, fsNone, @FoundLine, @FLastLineAddressesFoundFile)+  if Assigned(DbgInfo) and DbgInfo.HasInfo then begin+    if AMaxFindLineBelow > 0 then begin+    Result := DbgInfo.GetLineAddresses(AFileName, ALine, AResultList, fsNext, @FoundLine, @FLastLineAddressesFoundFile);+      if Result then+        Result := (FoundLine >= ALine) and (FoundLine <= ALine + AMaxFindLineBelow);+    end+    else+      Result := DbgInfo.GetLineAddresses(AFileName, ALine, AResultList, fsNone, @FoundLine, @FLastLineAddressesFoundFile);+  end   else     Result := False; end;@@ -2596,24 +2604,24 @@ function TDbgProcess.FindProcStartEndPC(const AAdress: TDbgPtr; out AStartPC, end;  function TDbgProcess.GetLineAddresses(AFileName: String; ALine: Cardinal;-  var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance): Boolean;+  var AResultList: TDBGPtrArray; ASymInstance: TDbgInstance; AMaxFindLineBelow: integer): Boolean; var   Lib: TDbgLibrary; begin   if ASymInstance <> nil then begin     if ASymInstance = self then begin-      Result := inherited GetLineAddresses(AFileName, ALine, AResultList);+      Result := inherited GetLineAddresses(AFileName, ALine, AResultList, AMaxFindLineBelow);     end     else begin-      Result := ASymInstance.GetLineAddresses(AFileName, ALine, AResultList);+      Result := ASymInstance.GetLineAddresses(AFileName, ALine, AResultList, AMaxFindLineBelow);       FLastLineAddressesFoundFile := ASymInstance.FLastLineAddressesFoundFile;     end;     exit;   end; -  Result := inherited GetLineAddresses(AFileName, ALine, AResultList);+  Result := inherited GetLineAddresses(AFileName, ALine, AResultList, AMaxFindLineBelow);   for Lib in FLibMap do begin-    if Lib.GetLineAddresses(AFileName, ALine, AResultList) then+    if Lib.GetLineAddresses(AFileName, ALine, AResultList, AMaxFindLineBelow) then       Result := True;     if Lib.FLastLineAddressesFoundFile then       FLastLineAddressesFoundFile := True;@@ -4187,7 +4195,7 @@ constructor TFpInternalBreakpointAtFileLine.Create(const AProcess: TDbgProcess;   FSymInstance := ASymInstance;    addr := nil;-  AProcess.GetLineAddresses(AFileName, ALine, addr, ASymInstance);+  AProcess.GetLineAddresses(AFileName, ALine, addr, ASymInstance, 1);   FFoundFileWithoutLine := AProcess.FLastLineAddressesFoundFile and (Length(addr) = 0);   inherited Create(AProcess, addr, AnEnabled); end; ---------------------------------------------------------------------- 440bx · 2024-04-19 22:36 I got my hands full... I'll wait until you've committed the solution you've chosen. ---------------------------------------------------------------------- YiannisKam · 2024-04-20 09:30 Sorry for the off-topic 440bx, but may I ask which font family you use in your code editor?  They look very cool. ---------------------------------------------------------------------- 440bx · 2024-04-20 11:59 Quote from: YiannisKam on April 20, 2024, 11:30:25 amSorry for the off-topic 440bx, but may I ask which font family you use in your code editor?  They look very cool. No problem.  I use the font that Borland distributed with Delphi 2 (and possibly some of the later versions.)  It's called "BorlandTE" (filename: BORTE.FON). Quite likely the best programming font ever designed.  Since its release I have not seen anything that matches it (though one font comes awfully close.) I cannot share it because it is copyrighted but, there is a clone that is _almost_ identical that is a free download, it is "raize" font.  It so close that if you don't have them both, it's not likely you'd notice that one isn't the other (hint: the numeral "0" is where the difference between the two is more noticeable.) I don't want to promote one site over another by offering a link.  Just do a search on "raize font".  There is one site where the font is rated at 4.9, I've used that site.  Any site you pick, be careful, they try to con you into clicking on something that is not the download button for the font but some junk they are peddling. There is another clone called "Borlandte-cjm" (free with attribution), what's interesting about it is that it is a truetype font and works in Visual Studio (the reason I looked for it and found it, I wanted to use Borland's font in VS.)  It's a good effort and the fact that it works in VS gives it value but, it's noticeably not as good as Borland's raster font but, you may want to look at it. Succinctly, first choice: BorlandTE, second (and close) choice: Raize, third choice (not as close as I'd like): Borlandte-cjm. For more information about fonts, comments and screenshots, I recommend the easy to read article https://darinhiggins.com/2012/05/18/best-programming-font/ There about 4 additional alternatives that article mentions that I would consider if I didn't have Borland's font. HTH. ---------------------------------------------------------------------- YiannisKam · 2024-04-20 12:08 Thank you very much for the valuable information, I really appreciate it. ---------------------------------------------------------------------- 440bx · 2024-04-20 12:11 Quote from: YiannisKam on April 20, 2024, 02:08:03 pmThank you very much for the valuable information, I really appreciate it. My pleasure.  You're welcome. ---------------------------------------------------------------------- VisualLab · 2024-04-20 12:30 Quote from: 440bx on April 19, 2024, 11:28:09 pmQuote from: Martin_fr on April 19, 2024, 10:50:39 pmBreakpoint on "begin" => I assume when you remove the breakpoint, then there is no blue dot on that line?    So the issue is that FPC does not generate code for that line. You're right.  There is no blue dot on the line. One thing I wonder: in Lazarus, blue dots appear in the editor gutter when debugging is started. They disappear when debugging is finished. In Delphi, blue dots appear after compilation/build is completed and remain after debugging is completed. What is the reason for this difference in the behavior of both IDEs? ---------------------------------------------------------------------- VisualLab · 2024-04-20 12:39 Quote from: 440bx on April 19, 2024, 10:10:08 pmAt first sight it seems there is enough space to put the red breakpoint dot to the left of the little note bitmap.  Basically, if FpDebug could place its breakpoint indicator flush left there would be two (2) visible bitmaps at that location instead of just one. Another possibility that does not entail moving the breakpoint indicator is to place the breakpoint indicator on top of of the Hint indicator (instead of having the Hint indicator on top as it is now.)  Personally, I think the breakpoint is a lot more important than the Hint. I compared the location of the blue dots in Delphi and Lazarus. In Delphi, dots are placed near the left edge of the gutter. When debugging, they usually do not conflict with other icons. The dots in Lazarus are placed at the right edge of the gutter. As a result, they are often covered by other icons. Maybe it would be possible to separate vertical areas (stripes) in the gutter in which different types of icons would be displayed, so that they would not overlap? Additionally, divided into editor modes: editing and debugging. In each of these modes, the editor could display different icons in separate areas of the gutter. ---------------------------------------------------------------------- 440bx · 2024-04-20 12:59 Quote from: VisualLab on April 20, 2024, 02:39:28 pmMaybe it would be possible to separate vertical areas (stripes) in the gutter in which different types of icons would be displayed, so that they would not overlap? Additionally, divided into editor modes: editing and debugging. In each of these modes, the editor could display different icons in separate areas of the gutter. I like the separate modes idea.  I think it makes sense to dedicate specific areas to specific purposes. I think that's the direction this is going because in a previous post Martin made it clear that the two icons should not overlap and there is enough space for both icons to be displayed (thereby creating the separation you suggested.) ---------------------------------------------------------------------- Martin_fr · 2024-04-20 15:55 Quote from: VisualLab on April 20, 2024, 02:30:31 pmOne thing I wonder: in Lazarus, blue dots appear in the editor gutter when debugging is started. They disappear when debugging is finished. In Delphi, blue dots appear after compilation/build is completed and remain after debugging is completed. What is the reason for this difference in the behavior of both IDEs? I don't know how Delphi implements them. If they are loaded from debug info, or if the Delphi compiler creates dedicated info for the IDE.  (Like fpc could (for other purposes) with "-b" generate info for an IDE)). In Lazarus, they come from the debug info. Without this, this, the IDE can not find out which source lines did generate machine code. (also that means, strictly speaking where fpc associates it, as sometimes fpc moves this when optimizing...). So historically, Lazarus got them using GDB, and that only happened when the debugger started. FpDebug too, only loads them when it starts debugging. Though having a build in reader, the IDE could read that info at an earlier point. That raises the same question as keeping them after debugging does => what for? As soon as you edit, there is a chance that they become inaccurate. That is true even during debugging, but usually with more extensive editing being done while the debugger does not run, the issue gets more noticeable. If you break a line into 2, and then join each part with other lines (that may or may not have been added after the last compilation) then the blue dots aren't very accurate any more. Also as for seeing if IFDEFed code is active, the Lazarus IDE highlights that without the need of compiling. The only part it wont show you is dead code elimination.  "if false then". The only case were loading them after compile would be needed is, if you set your project to "not compile automatically". So you can - compile - edit - run/debug without compiling the recent edits Then of course you want the blue dots after compile, because they secretly contain the mapping of any changed line numbers due to edit after the compile (which helps setting breakpoints). (Afaik delphi does not map line numbers for edited code ?) Anyway, I also think of the blue dots as a nice indicator that the debugger is running. So thats a point for the current behaviour. ---------------------------------------------------------------------- Martin_fr · 2024-04-20 16:01 Quote from: VisualLab on April 20, 2024, 02:39:28 pmI compared the location of the blue dots in Delphi and Lazarus. In Delphi, dots are placed near the left edge of the gutter. When debugging, they usually do not conflict with other icons. The dots in Lazarus are placed at the right edge of the gutter. As a result, they are often covered by other icons. Maybe it would be possible to separate vertical areas (stripes) in the gutter in which different types of icons would be displayed, so that they would not overlap? Additionally, divided into editor modes: editing and debugging. In each of these modes, the editor could display different icons in separate areas of the gutter. Left vs right isn't the issue, or is it. Just were each type of icon goes compared to others. Bookmarks go into the 1st (leftmost) column. All the rest goes into the 2nd column => well, that changed: https://gitlab.com/freepascal.org/lazarus/lazarus/-/issues/40914 Even in Delphi, afaik breakpoints themself cover the blue dot. So, this is only about error/warning/note icons? They could be moved to the bookmark column (unless a bookmark is also set on that line). I don't know if they would benefit much from having a dedicated 3rd column. Btw, you can set the gutter to provide 3 columns (editor options > display / 3.99). But that wont dedicate any of the columns to anything. ---------------------------------------------------------------------- VisualLab · 2024-04-20 16:40 Quote from: Martin_fr on April 20, 2024, 05:55:08 pmAs soon as you edit, there is a chance that they become inaccurate. That is true even during debugging, but usually with more extensive editing being done while the debugger does not run, the issue gets more noticeable. If you break a line into 2, and then join each part with other lines (that may or may not have been added after the last compilation) then the blue dots aren't very accurate any more. I think someone mentioned this on the forum before. In any case, this is supposed to inform the programmer which lines of code are being compiled (converted to machine code). I found this description in the Delphi documentation: http://docwiki.embarcadero.com/RADStudio/Alexandria/en/Setting_and_Mod ifying_Breakpoints Attempting to edit the code causes the blue dots to disappear from the Delphi editor's gutter (I just checked). All you need to do is position the cursor and press the ENTER key. But from time to time there are errors in the position (vertical) of these dots. Here is one description of this problem: https://ideasawakened.com/post/rad-studio-10-4-2-is-now-available- with-possible-cure-for-the-blue-dot-problem It seems that in Delphi this information is generated at compile time and displayed after the process is completed. Quote from: Martin_fr on April 20, 2024, 05:55:08 pmAlso as for seeing if IFDEFed code is active, the Lazarus IDE highlights that without the need of compiling. The only part it wont show you is dead code elimination.  "if false then". Yes, it works fine. ---------------------------------------------------------------------- Martin_fr · 2024-04-20 18:15 Quote from: VisualLab on April 20, 2024, 06:40:04 pmIn any case, this is supposed to inform the programmer which lines of code are being compiled (converted to machine code). I found this description in the Delphi documentation: http://docwiki.embarcadero.com/RADStudio/Alexandria/en/Setting_and_Mod ifying_Breakpoints Attempting to edit the code causes the blue dots to disappear from the Delphi editor's gutter (I just checked). All you need to do is position the cursor and press the ENTER key. Quote from: Delphi DocsDuring a debugging session, any line of code that is eligible for a breakpoint is marked with a blue dot Blue dot in the left gutter of the Code Editor. So it is for debugging. Yes, you can set breakpoints before starting the debugger. But you can set them even before compiling. For solving "where to set my breakpoint, so that it will work", it is better to make sure breakpoints on non-code line will break at the next line (within reasonable limits and conditions). Personally I don't see an advantage to load the blue dots at an earlier point. Especially if you compile, without running, then the very next think that is likely done, is that you keep editing. So the dots would immediately be removed again. But very well, ok, maybe someone has a workflow in which they do matter.... The other issue is that even if it were implemented, it then needs a debug info reader for each file format. Compiling for remote debugging, and that might be in gdb, and gdb only => meaning you have to initialize gdb as if you want to debug, just to read the dots. And code needs to remember that it was loaded pre-debugging, so it can be cleared at an appropriate time. And on option (though that is simple), because I definitely see them as indicator that the debugger is running. .... Personally, I would need to be convinced that there is a huge benefit to it, before even considering accepting a patch for it. ---------------------------------------------------------------------- 440bx · 2024-04-20 19:01 Quote from: Martin_fr on April 20, 2024, 08:15:08 pmPersonally I don't see an advantage to load the blue dots at an earlier point. I think having the blue dots be indicators that a.) the compiler generated code for that line of Pascal and b.) that the debugger is active is their most logical use.  I think that's pretty much what you're saying and, if that's the case, I obviously agree. IMO, having the blue dots at any other time is just too error prone and actually confusing since it is no longer clear what they truly represent. If the debugger isn't running then the programmer should simply presume that a source line of code is a place where the debugger can break.  That's not always the case but, the debugger cannot inform the user of that if it's not running.  Once running, the blue dots tell the true story. As I was typing this, a thought crossed my mind (note: this not a feature request, just thinking out loud), in theory the compiler could always generate an instruction for every line of Pascal source.  For instance, if needed it could generate a noop for a particular source line (say a "begin", preferably at the very end of the "begin" prologue) and put a symbol in the debug tables for the debugger to use.  Optimization level: "minus 1" ---------------------------------------------------------------------- Martin_fr · 2024-04-21 15:19 OK, so if you set a breakpoint on a "non blue dot" line, FpDebug can now stop at the next line. (depending on settings). "next line" is the most logical choice, since that is right after the breakpoint gets passed. Please note, if compiled with -O1 or above: Code: Pascal  [Select][+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i if foo then   exit; // or break / continue ...the "exit" line may not have code. In that case "next line" wont be reached (or well, it will, but only if exit is not executed), as the code takes a different path. However, there is no way to solve that in the debugger or IDE. If exit has no (identifiable) code to break on, then it can't be done. (Compile with -O- instead) There is a setting "BreakpointSearchMaxLines" (default 3) - set to 0 means breakpoints will only be on the exact line. - set to 1..25 will mean to look up to that many lines below. The 1..25 has one exception => if the breakpoint is outside the function (defined as by above the first line for which fpc provided debug info), then only ONE line below will be checked. That prevents for example that breakpoints that are meant for the previous procedure (but are below it) will be attributed to the next. Most functions will have code on the functions "begin" line => and usually breakpoint in front of that are rare. Please test. Note, that I also improved/fixed the ability to have multiply breakpoints hit. That was already possible for Watchpoint + breakpoint, or for address/asm break and source-break. But now, you can also have several breakpoints stacked above one line. (And each can have actions, conditions, disabled, hitcount, ...) ---------------------------------------------------------------------- 440bx · 2024-04-21 15:55 Quote from: Martin_fr on April 21, 2024, 05:19:12 pmPlease test. What follows is from a rather quick test. The "break on next blue dot line" seems to be working fine. Please refer to the screenshot.  The breakpoint is placed on line 3456 for which there is no blue dot, i.e, no code, and the debugger correctly and as expected, broke on line 3460 which is the next line where there are instructions. One thought crossed my mind, when the breakpoint is set, the debugger doesn't know that the line has no code but, once the program is running and the breakpoint acts upon line 3460 instead of 3456, it would be nice if the debugger would reset the line number to the line number where the breakpoint occurred. IOW, initially the breakpoint would display line 3456 as where it is set but, after the breakpoint is triggered and noticing that it didn't trigger on the line it is set on, then it should automatically (possibly user-setting controlled) reset the line number to the line number where it actually happened.  This would cause the breakpoint visual indicator (in the screenshot, a red line and red dot) to move to the actual line (instead of remaining on the "end" line.)    This doesn't rise to the level of "feature request" but, I think it would be a nice "polishing" touch. ETA: Added: reset the line number ---------------------------------------------------------------------- 440bx · 2024-04-21 16:06 I forgot to mention in the previous post... setting a breakpoint where there is a hint causes the hint to move out of the way   great stuff... the breakpoint is (at least to me) way more important than the hint. ---------------------------------------------------------------------- Martin_fr · 2024-04-21 18:42 Quote from: 440bx on April 21, 2024, 05:55:29 pmOne thought crossed my mind, when the breakpoint is set, the debugger doesn't know that the line has no code but, once the program is running and the breakpoint acts upon line 3460 instead of 3456, it would be nice if the debugger would reset the line number to the line number where the breakpoint occurred. IOW, initially the breakpoint would display line 3456 as where it is set but, after the breakpoint is triggered and noticing that it didn't trigger on the line it is set on, then it should automatically (possibly user-setting controlled) reset the line number to the line number where it actually happened.  This would cause the breakpoint visual indicator (in the screenshot, a red line and red dot) to move to the actual line (instead of remaining on the "end" line.) Not by default. Imagine you temp commented a line (or IFDEF). Now you break on the next. And if you uncomment, all is back to what it was. But if the breakpoint moved, that does not work. It will be permanently moved. About manually adjusting the breakpoint location: - Currently that can be done by editing the line number in the break properties. - On my todo list: drag and drop of breakpoints. (and imho that would make it easy enough) ---------------------------------------------------------------------- Martin_fr · 2024-04-21 18:47 Quote from: 440bx on April 21, 2024, 06:06:49 pmI forgot to mention in the previous post... setting a breakpoint where there is a hint causes the hint to move out of the way   great stuff... the breakpoint is (at least to me) way more important than the hint. If you mean, the hint moving into the place of the bookmark => yes. If there is a bookmark a hint and a breakpoint => the order between breakpoint and hint may be partly random. I don't know what the current sort method is. But I have seen different ordering.... However, 3.99 will shrink those 3 and you still see them all. There are still some hickups, like the current line indicator sometimes shows in the wrong column.... (I really opened Pandoras box... A lot of code just depended on only one column for all non bookmarks) ---------------------------------------------------------------------- Martin_fr · 2024-04-21 19:17 Btw, 3.99   alt-mouse-click a breakpoint in the gutter (or to set a new breakpoint) => opens break properties. (for editing the line number and all else) ---------------------------------------------------------------------- 440bx · 2024-04-21 20:11 Alt-mouse click is a nice "shortcut" to set a breakpoint and adjust its properties.  Just tried and it's rather convenient. About the hint icon moving... yes, that's what I meant. Lastly, I see what you're saying about moving the breakpoint.  I hadn't thought about an "ifdef" being the cause of having no code on that line.  Moving the breakpoint in that case isn't desirable. About the drag and drop of breakpoints, that would be a nice, very convenient feature.  Definitely welcome. ---------------------------------------------------------------------- Martin_fr · 2024-04-22 00:32 Quote from: VisualLab on April 20, 2024, 02:39:28 pmI compared the location of the blue dots in Delphi and Lazarus. In Delphi, dots are placed near the left edge of the gutter. When debugging, they usually do not conflict with other icons. The dots in Lazarus are placed at the right edge of the gutter. As a result, they are often covered by other icons. Maybe it would be possible to separate vertical areas (stripes) in the gutter in which different types of icons would be displayed, so that they would not overlap? Additionally, divided into editor modes: editing and debugging. In each of these modes, the editor could display different icons in separate areas of the gutter. Now warnings also default to the 1st column (2nd column, if you configured to show 3 columns). So the blue dots will be less often covered. Of course, if you have several icons fighting for one column, then they will use the other columns. Mind that if you join lines, and each of them has a bookmark before you join them, you can end up with multiple bookmarks on a single line.... (Same for breakpoints)