One idea using the mdframed
package and its middleextra
, secondextra
keys to add a continued caption:
\documentclass[12pt,a4paper]{article}
\usepackage[a5paper]{geometry}% just for the example
\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=west] at (O|-P)
{\lstlistingname~\thelstlisting\ (Cont.):~\mylstcaption};},
secondextra={
\node[anchor=west] at (O|-P)
{\lstlistingname~\thelstlisting\ (Cont.):~\mylstcaption};},
splittopskip=2\baselineskip
]{lstlisting}
\begin{document}
\renewcommand\mylstcaption{Example listing of code}
\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}
Before each lstlisting
environment you redefine \mylstcaption
with the text of the caption.
For \lstinpulisting
, the general idea is the same, but using this time a \newmdenv
; to avoid unnecessary code duplication, a style was defined:
\documentclass[12pt,a4paper]{article}
\usepackage[a5paper]{geometry}% just for the example
\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{}
\mdfdefinestyle{mymdstyle}{
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
}
\surroundwithmdframed[style=mymdstyle]{lstlisting}
\newmdenv[style=mymdstyle]{mdlisting}
\begin{document}
\renewcommand\mylstcaption{Example listing of code}
\begin{mdlisting}
\lstinputlisting[language=C, caption=\mylstcaption, label=lst:c1]{file}
\end{mdlisting}
\end{document}
Update
Here's now the same idea but using now tcolorbox
:
\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}
Best Answer
As example for the first part, a breakable tcb listing box using minted (tcb code somewhat adapted from another answer on this site about quoting; javascript code is from this page):
There are three or four ways of dealing with the perennial problem of wrapping long lines: here, some (manual) line-wrapping and indentation removal has been done to the first code block, as illustration.
MWE
js file: