2

I am following the accepted answer from this question to extend an lstlisting across multiple pages. It works great, however if my caption is too long the continued caption doesn't wrap, and this is an issue as I have to use a 2-column format.

For example, if I have:

Listing 1: Excerpted implementation of sorting application.

The first caption appears correct as:

Listing 1: Excerpted implementation of
sorting application.

However, when it spans multiple pages, the caption on the continued page doesn't wrap and writes into the second column.

For reference, here is the initial definition:

\usepackage{listings}
\usepackage{caption}
\usepackage[framemethod=tikz]{mdframed}

\lstset{
breaklines=true,
breakatwhitespace=false,
frame=single,
}

\newcommand\mylstcaption{}

\surroundwithmdframed[
hidealllines=true,
middleextra={
  \node[anchor=west] at (O|-P)
    {\lstlistingname~\thelstlisting\  (Cont.):~\mylstcaption};},
secondextra={
  \node[anchor=west] at (O|-P)
    {\lstlistingname~\thelstlisting\  (Cont.):~\mylstcaption};},
splittopskip=2\baselineskip
]{lstlisting}

And a sample implementation:

\renewcommand\mylstcaption{Excerpted C implementation of legacy sorting application.}
\begin{lstlisting}[language=C, caption=\mylstcaption, label=l:sort1]
...
\end{lstlisting}
2

You can provide a sensible value (\columnwidth, for example) for the text width key of the \nodes:

\documentclass[12pt,a4paper,twocolumn]{article}
\usepackage[utf8x]{inputenc}
\usepackage{listings}
\usepackage{caption}
\usepackage[framemethod=tikz]{mdframed}

\lstset{
breaklines=true,
breakatwhitespace=false,
xleftmargin=1em,
frame=single,
numbers=left,
numbersep=5pt,
}

\newcommand\mylstcaption{}

\surroundwithmdframed[
hidealllines=true,
middleextra={
  \node[anchor=south west,text width=\columnwidth] at (O|-P)
    {\lstlistingname~\thelstlisting\  (Cont.):~\mylstcaption};},
secondextra={
  \node[anchor=south west,text width=\columnwidth] at (O|-P)
    {\lstlistingname~\thelstlisting\  (Cont.):~\mylstcaption};},
splittopskip=2\baselineskip
]{lstlisting}

\begin{document}

\renewcommand\mylstcaption{Example listing of code with a long caption spanning several lines in a two-column document. this is just a test for the example.}
\begin{lstlisting}[language=C, caption=\mylstcaption, label=lst:c1]

struct safe_buffer {
struct list_head node;

/* original request */
void    *ptr;
size_t  size;
int direction;

/* safe buffer info */
struct dmabounce_pool *pool;
void    *safe;
dma_addr_t  safe_dma_addr;
};

struct dmabounce_pool {
unsigned long   size;
struct dma_pool *pool;
#ifdef STATS
unsigned long   allocs;
#endif
};

struct dmabounce_device_info {
struct device *dev;
struct list_head safe_buffers;
#ifdef STATS
unsigned long total_allocs;
unsigned long map_op_count;
unsigned long bounce_count;
int attr_res;
#endif
struct dmabounce_pool   small;
struct dmabounce_pool   large;

rwlock_t lock;

int (*needs_bounce)(struct device *, dma_addr_t, size_t);
};

#ifdef STATS
static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
device_info->small.allocs,
device_info->large.allocs,
device_info->total_allocs - device_info->small.allocs -
device_info->large.allocs,
device_info->total_allocs,
device_info->map_op_count,
device_info->bounce_count);
}

static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
#endif

\end{lstlisting}

\end{document}

enter image description here

Just for completeness, here's the same idea but using tcolorbox and its interaction with listings:

\documentclass[12pt,a4paper]{article}
\usepackage[utf8x]{inputenc}
\usepackage[many]{tcolorbox}
\tcbuselibrary{listings}

\lstset{
  breaklines=true,
  breakatwhitespace=false,
  xleftmargin=1em,
  frame=single,
  numbers=left,
  numbersep=5pt,
}

\newtcblisting{TCBlisting}[1][]{
  breakable,
  enhanced,
  arc=0pt,
  outer arc=0pt,
  boxrule=0pt,
  colback=white,
  listing only,
  listing remove caption=false,
  listing options={#1},
  overlay middle and last={
  \node[anchor=south west,text width=\columnwidth] at (frame.north west)
    {\lstlistingname~\thelstlisting\  (Cont.):~\mylstcaption};
  }
}

\newcommand\mylstcaption{}

\begin{document}

\renewcommand\mylstcaption{Example listing of code with a long caption spanning several lines in a two-column document. this is just a test for the example.}
\begin{TCBlisting}[language=C,caption={\mylstcaption}]
struct safe_buffer {
struct list_head node;

/* original request */
void    *ptr;
size_t  size;
int direction;

/* safe buffer info */
struct dmabounce_pool *pool;
void    *safe;
dma_addr_t  safe_dma_addr;
};

struct dmabounce_pool {
unsigned long   size;
struct dma_pool *pool;
#ifdef STATS
unsigned long   allocs;
#endif
};

struct dmabounce_device_info {
struct device *dev;
struct list_head safe_buffers;
#ifdef STATS
unsigned long total_allocs;
unsigned long map_op_count;
unsigned long bounce_count;
int attr_res;
#endif
struct dmabounce_pool   small;
struct dmabounce_pool   large;

rwlock_t lock;

int (*needs_bounce)(struct device *, dma_addr_t, size_t);
};

#ifdef STATS
static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
device_info->small.allocs,
device_info->large.allocs,
device_info->total_allocs - device_info->small.allocs -
device_info->large.allocs,
device_info->total_allocs,
device_info->map_op_count,
device_info->bounce_count);
}

static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
#endif

\end{TCBlisting}
\end{document}
\begin{lstlisting}[language=C, caption=\mylstcaption, label=lst:c1]

struct safe_buffer {
struct list_head node;

/* original request */
void    *ptr;
size_t  size;
int direction;

/* safe buffer info */
struct dmabounce_pool *pool;
void    *safe;
dma_addr_t  safe_dma_addr;
};

struct dmabounce_pool {
unsigned long   size;
struct dma_pool *pool;
#ifdef STATS
unsigned long   allocs;
#endif
};

struct dmabounce_device_info {
struct device *dev;
struct list_head safe_buffers;
#ifdef STATS
unsigned long total_allocs;
unsigned long map_op_count;
unsigned long bounce_count;
int attr_res;
#endif
struct dmabounce_pool   small;
struct dmabounce_pool   large;

rwlock_t lock;

int (*needs_bounce)(struct device *, dma_addr_t, size_t);
};

#ifdef STATS
static ssize_t dmabounce_show(struct device *dev, struct device_attribute *attr,
char *buf)
{
struct dmabounce_device_info *device_info = dev->archdata.dmabounce;
return sprintf(buf, "%lu %lu %lu %lu %lu %lu\n",
device_info->small.allocs,
device_info->large.allocs,
device_info->total_allocs - device_info->small.allocs -
device_info->large.allocs,
device_info->total_allocs,
device_info->map_op_count,
device_info->bounce_count);
}

static DEVICE_ATTR(dmabounce_stats, 0400, dmabounce_show, NULL);
#endif

\end{lstlisting}

\end{document}
  • Heh, I debated posting a comment asking for clarification in your answer to the other question, but figured this would get more visibility. Thanks! – the_e Jul 23 '15 at 14:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.