diff --git a/ivette/src/dome/renderer/dome.tsx b/ivette/src/dome/renderer/dome.tsx
index f09729d827c30505a63dab087f11065d71d79d07..0edda413386105a2b24ff69313cb8dc09149229b 100644
--- a/ivette/src/dome/renderer/dome.tsx
+++ b/ivette/src/dome/renderer/dome.tsx
@@ -518,6 +518,29 @@ export function useUpdate(...events: Event<any>[]) {
   });
 }
 
+/**
+   Hook to re-render when a Promise returns.
+   The promise will be typically created by using `React.useMemo()`.
+   The hook returns three informations:
+   - result: the promise result if it succeeds, undefined otherwise;
+   - error: the promise error if it fails, undefined otherwise;
+   - loading: the promise status, true if the promise is still running.
+*/
+export function usePromise<T>(job: Promise<T>) {
+  const [result, setResult] = React.useState<T | undefined>();
+  const [error, setError] = React.useState<Error | undefined>();
+  const [loading, setLoading] = React.useState(true);
+  React.useEffect(() => {
+    let cancel = false;
+    const doCancel = () => { if (!cancel) setLoading(false); return cancel; };
+    const onResult = (x: T) => { if (!doCancel()) setResult(x); };
+    const onError = (e: Error) => { if (!doCancel()) setError(e); };
+    job.then(onResult, onError);
+    return () => { cancel = true; };
+  }, [job]);
+  return { result, error, loading };
+}
+
 // --------------------------------------------------------------------------
 // --- Timer Hooks
 // --------------------------------------------------------------------------
diff --git a/ivette/src/dome/renderer/text/buffers.ts b/ivette/src/dome/renderer/text/buffers.ts
index 02dd4616f8da30a5666b904e008fbfea43b7779e..712089fa924a872903f7903c867cd41b43dfdecd 100644
--- a/ivette/src/dome/renderer/text/buffers.ts
+++ b/ivette/src/dome/renderer/text/buffers.ts
@@ -478,6 +478,19 @@ export class RichTextBuffer extends Emitter {
     }
   }
 
+  /**
+     Requires all connected views to select the specified line and to place it
+     at the top of their displays.
+
+     @param line - the line number to select
+  */
+  setCursorOnTop(line: number): void {
+    this.forEach((cm) => {
+      cm.setCursor(cm.lastLine());
+      cm.setCursor(line - 1);
+    });
+  }
+
   // --------------------------------------------------------------------------
   // --- Document Linking
   // --------------------------------------------------------------------------
diff --git a/ivette/src/frama-c/kernel/SourceCode.tsx b/ivette/src/frama-c/kernel/SourceCode.tsx
index b635b6facafb4e03e68f036e3b61d139dbe154bc..aaf770e7399bc4c1bb8c4709fe7982c573ad930f 100644
--- a/ivette/src/frama-c/kernel/SourceCode.tsx
+++ b/ivette/src/frama-c/kernel/SourceCode.tsx
@@ -33,14 +33,14 @@ import { RichTextBuffer } from 'dome/text/buffers';
 import { Text } from 'dome/text/editors';
 import { TitleBar } from 'ivette';
 import * as Preferences from 'ivette/prefs';
-import { functions, markerInfo, source } from 'frama-c/api/kernel/ast';
+import { functions, markerInfo } from 'frama-c/api/kernel/ast';
+import { Code } from 'dome/controls/labels';
+import { Hfill } from 'dome/layout/boxes';
+import * as Path from 'path';
 
 import 'codemirror/addon/selection/active-line';
 import 'codemirror/addon/dialog/dialog.css';
-import 'codemirror/addon/dialog/dialog';
 import 'codemirror/addon/search/searchcursor';
-import 'codemirror/addon/search/search';
-import 'codemirror/addon/search/jump-to-line';
 
 // --------------------------------------------------------------------------
 // --- Pretty Printing (Browser Console)
@@ -52,13 +52,28 @@ const D = new Dome.Debug('Source Code');
 // --- Source Code Printer
 // --------------------------------------------------------------------------
 
+// The SourceCode component, producing the GUI part showing the source code
+// corresponding to the selected function.
 export default function SourceCode() {
 
   // Hooks
-  const buffer = React.useMemo(() => new RichTextBuffer(), []);
+  const [buffer] = React.useState(new RichTextBuffer());
   const [selection] = States.useSelection();
   const theFunction = selection?.current?.fct;
   const theMarker = selection?.current?.marker;
+  const markersInfo = States.useSyncArray(markerInfo);
+  const functionsData = States.useSyncArray(functions).getArray();
+
+  // Retrieving the file name and the line number from the selection and the
+  // synchronized tables.
+  const sloc =
+    (theMarker && markersInfo.getData(theMarker)?.sloc) ??
+    (theFunction && functionsData.find((e) => e.name === theFunction)?.sloc);
+  const file = sloc ? sloc.file : '';
+  const line = sloc ? sloc.line : 0;
+  const filename = Path.parse(file).base;
+
+  // Title bar buttons, along with the parameters for our text.
   const { buttons: themeButtons, theme, fontSize, wrapText } =
     Preferences.useThemeButtons({
       target: 'Source Code',
@@ -68,46 +83,21 @@ export default function SourceCode() {
       disabled: !theFunction,
     });
 
-  const markersInfo = States.useSyncArray(markerInfo);
-  const functionsData = States.useSyncArray(functions).getArray();
-
-  const currentFile = React.useRef<string>();
-
-  React.useEffect(() => {
-    // Async source file loading and jump to line/location.
-    async function loadSourceCode(sloc?: source) {
-      if (sloc) {
-        const { file, line } = sloc;
-        try {
-          if (file !== currentFile.current) {
-            currentFile.current = file;
-            const content = await readFile(file);
-            buffer.setValue(content);
-          }
-          buffer.forEach((cm) => { cm.setCursor(line - 1); });
-        } catch (err) {
-          D.error(`Fail to load source code file ${file}.`);
-        }
-      }
-    }
-    // Actual source code loading upon function or marker update.
-    const sloc =
-      /* markers have more precise source location */
-      (theMarker && markersInfo.getData(theMarker)?.sloc)
-      ??
-      (theFunction && functionsData.find((e) => e.name === theFunction)?.sloc);
-    if (sloc) {
-      loadSourceCode(sloc);
-    } else {
-      currentFile.current = undefined;
-      buffer.clear();
-    }
-  }, [buffer, functionsData, markersInfo, theFunction, theMarker]);
+  // Updating the buffer content.
+  const errorMsg = () => { D.error(`Fail to load source code file ${file}`); };
+  const onError = () => { if (file) errorMsg(); return ''; };
+  const read = () => readFile(file).catch(onError);
+  const text = React.useMemo(read, [file, onError]);
+  const { result } = Dome.usePromise(text);
+  React.useEffect(() => buffer.setValue(result), [buffer, result]);
+  React.useEffect(() => buffer.setCursorOnTop(line), [buffer, line, result]);
 
-  // Component
+  // Building the React component.
   return (
     <>
       <TitleBar>
+        <Code title={file}>{filename}</Code>
+        <Hfill />
         {themeButtons}
       </TitleBar>
       <Text