Excellent. My only advice is to try to use DBGrid.SelectedColumn, DBGrid.SelectedField and notice TField.OnGetText sends the field in question as Sender.
I also advice you to define all fieldname as constants. ie: fnLinkSource = ''link_source'
I can see OnGetText is identical for both 'link_source' & 'link_pdf', and the field in question is Sender, so why not just use one method for both?
Note: Column indexes are not a robust way to identify a column since columns can be inserted or moved.
The last thing you want is for code to break when table structures are modified. You can also manually add TDBGrid columns which arn't associated to a field, which means you can add push buttons for records without adding a 'dummy' field.
Just keep an eye on issues that can break code, or situations where you cant edit the table structure. Imagine working on a table for a company that refuses you to add two dummy fields. What do you do? Or, if you are working on a table were the company wants different ordering of columns , or some columns to be readonly or hidden. Maybe they store time as 24 hour, but want users to be able to enter roster times of 1:00 to mean 13:00, since no one starts work at 1:00? ie: shifting the 12 hour boundary. That is all done via OnGetText/OnSetText
The solutions are there, just keep to the wise coding styles. and yep, column indexes are bad.