scr_dump(5) File formats scr_dump(5)

scr_dump - قالب فایل تخلیه صفحه نمایش ncurses

کتابخانه curses به برنامه‌ها این امکان را می‌دهد که محتویات یک پنجره را با استفاده از scr_dump یا putwin در یک فایل خارجی بنویسند و آن را با استفاده از scr_restore یا getwin مجدداً بازخوانی کنند.

توابع putwin و getwin کار اصلی را انجام می‌دهند؛ در حالی که scr_dump و scr_restore به‌طور مناسب کل صفحه نمایش، یعنی stdscr را ذخیره و بازیابی می‌کنند.

پیاده‌سازی دیرینه تخلیه صفحه نمایش در ncurses6 برای رفع مشکلات رویکرد پیشین بازنگری شد:

•
یک «شماره جادویی» (“magic number”) در ابتدای فایل تخلیه نوشته می‌شود که به برنامه‌هایی مانند file(1) امکان می‌دهد فایل‌های تخلیه curses را شناسایی کنند.
از آنجا که ncurses6 از قالب جدیدی استفاده می‌کند، این امر نیازمند شماره جادویی جدیدی بود که توسط سایر برنامه‌ها استفاده نشده باشد. این عدد ۱۶ بیتی استفاده‌نشده بود:
0x8888 (octal “\210\210”)

اما برای اطمینان بیشتر، این عدد ۳۲ بیتی انتخاب شد:

0x88888888 (octal “\210\210\210\210”)

این الگویی است که به نگه‌دارندگان برنامه file ارائه شده است:

#
# ncurses5 (and before) did not use a magic number,
# making screen dumps "data".
#
# ncurses6 (2015) uses this format, ignoring byte-order
0    string    \210\210\210\210ncurses    ncurses6 screen image
#
•
تخلیه‌های صفحه نمایش به شکل متنی نوشته می‌شوند تا اندازه داده‌های داخلی مستقیماً به قالب تخلیه وابسته نباشد و کتابخانه بتواند تخلیه‌ها را از پیکربندی‌های کاراکتر باریک (narrow) یا کاراکتر عریض (wide) بخواند.
پیکربندی کتابخانه narrow کاراکترها و ویژگی‌های تصویری را در یک chtype ۳۲ بیتی نگه می‌دارد، در حالی که کتابخانه wide-character این اطلاعات را در ساختار cchar_t ذخیره می‌کند که بسیار بزرگ‌تر از ۳۲ بیت است.
  • خواندن یک تخلیه صفحه در ترمینالی با اندازه صفحه متفاوت امکان‌پذیر است، زیرا کتابخانه بر حسب نیاز صفحه را کوتاه (truncate) یا با فضای خالی پر می‌کند.
  • تابع getwin در ncurses6 می‌تواند تخلیه‌های صفحه قدیمی مربوط به ncurses5 را نیز بخواند.

ویژگی تخلیه صفحه در ژوئن ۱۹۹۵ به ncurses افزوده شد. اگرچه در سال‌های پس از آن اصلاحات و بهبودهایی صورت گرفت، طرح کلی پایه بدون تغییر باقی ماند:

  • ساختار WINDOW به صورت باینری نوشته می‌شد.
  • ساختار WINDOW به خطوطی از داده‌ها ارجاع می‌دهد که به صورت آرایه‌ای از داده‌های باینری به دنبال WINDOW نوشته می‌شدند.
  • هنگامی که getwin پنجره را بازیابی می‌کرد، آفست‌ها را در آرایه داده‌های خطوط ردیابی می‌کرد و ساختار WINDOW را که مجدداً در حافظه خوانده شده بود تنظیم می‌نمود.

این روش شبیه به Unix System V است، اما «شماره جادویی» (“magic number”) را برای شناسایی قالب فایل نمی‌نویسد.

هیچ قالب استانداردی برای تخلیه‌های صفحه curses وجود ندارد. در ادامه بررسی کوتاهی از پیاده‌سازی‌های موجود آمده است.

سند X/Open Curses نسخه ۷ جزئیات اندکی را مشخص کرده است. در این سند آمده است (تاکید پررنگ افزوده شده است):

“تابع getwin() داده‌های مرتبط با پنجره را که توسط putwin() در فایل ذخیره شده است می‌خواند. سپس این تابع با استفاده از آن داده‌ها، پنجره جدیدی را ایجاد و مقداردهی اولیه می‌کند.

تابع putwin() تمامی داده‌های مرتبط با win را با استفاده از یک قالب نامشخص (unspecified format) در جریان stdio که filep به آن اشاره دارد می‌نویسد. این اطلاعات بعداً با استفاده از getwin() قابل بازیابی است.”

در اواسط دهه ۱۹۹۰ که سند X/Open Curses نوشته شد، هنوز سیستم‌های System V از کتابخانه‌های قدیمی‌تر و با قابلیت کمتر curses استفاده می‌کردند. کتابخانه BSD curses برای X/Open مطرح نبود زیرا معیارهای انطباق سطح پایه را برآورده نمی‌کرد؛ به ncurses(3NCURSES) مراجعه کنید.

کتابخانه System V curses قالب فایل را با نوشتن یک «شماره جادویی» (“magic number”) در ابتدای فایل تخلیه شناسایی می‌کرد. داده‌های WINDOW و خطوط متن همگی در قالب باینری پس از آن قرار می‌گیرند.

کتابخانه Solaris curses دارای تعاریف زیر است:

/* terminfo magic number */
#define MAGNUM  0432
/* curses screen dump magic number */
#define SVR2_DUMP_MAGIC_NUMBER  0433
#define SVR3_DUMP_MAGIC_NUMBER  0434

بدین معنی که این ویژگی احتمالاً در SVr2 (سال ۱۹۸۴) معرفی شد و در SVr3 (سال ۱۹۸۷) بهبود یافت. کتابخانه Solaris curses شماره جادویی برای SVr4 (سال ۱۹۸۹) ندارد. سایر سیستم‌عامل‌های System V (مانند AIX و HP-UX) از شماره جادویی استفاده می‌کنند که معادل تعریف زیر است:

/* curses screen dump magic number */
#define SVR4_DUMP_MAGIC_NUMBER  0435

این عدد هشت‌هشتی (octal) در قالب بایت‌ها برابر 001، 035 است. از آنجا که بیشتر تولیدکنندگان یونیکس در آن زمان از سخت‌افزارهای با ترتیب بایت بزرگ‌تر (big-endian) استفاده می‌کردند، شماره جادویی با بایت مرتبه بالاتر در ابتدا نوشته می‌شود:

\001\035

پس از شماره جادویی، ساختار WINDOW و داده‌های خطوط در قالب باینری نوشته می‌شوند. اگرچه شماره جادویی مورد استفاده این سیستم‌ها را می‌توان با od(1) مشاهده کرد، هیچ‌یک از آن‌ها قالب مورد استفاده برای تخلیه‌های صفحه را مستند نکرده‌اند.

آن‌ها حتی درون خانواده System V نیز از قالبی یکسان استفاده نمی‌کنند. برنامه آزمایشی savescreen در ncurses برای جمع‌آوری اطلاعات این صفحه راهنما به کار گرفته شد. این برنامه تخلیه‌هایی با اندازه‌های متفاوت تولید کرد (همگی روی سخت‌افزار ۶۴ بیتی و صفحات ۴۰×۸۰):

  • سیستم AIX (۵۱۸۱۷ بایت)
  • سیستم HP-UX (۹۰۰۹۳ بایت)
  • سیستم Solaris 10 (۱۳۲۷۳ بایت)
  • ncurses5 (۱۲۸۸۸ بایت)

همان‌طور که در بالا اشاره شد، Solaris curses هیچ شماره جادویی متناظر با curses در SVr4 ندارد. این امر عجیب است، زیرا سولاریس نخستین سیستم‌عاملی بود که دستورالعمل‌های SVr4 را برآورده ساخت. علاوه بر این، سولاریس دو نسخه از curses را ارائه می‌دهد:

  • کتابخانه پیش‌فرض curses از شماره جادویی SVr3 استفاده می‌کند.
  • یک کتابخانه جایگزین curses (که آن را xcurses می‌نامیم) موجود در /usr/xpg4، از یک قالب متنی بدون شماره جادویی استفاده می‌کند.
طبق اعلان حق نشر آن، این کتابخانه xcurses توسط MKS (Mortice Kern Systems) بین سال‌های ۱۹۹۰ تا ۱۹۹۵ توسعه یافته است.
همانند ncurses6، شامل یک هدر با پارامترها است. برخلاف ncurses6، محتویات پنجره تکه‌تکه نوشته می‌شوند؛ همراه با مختصات و ویژگی‌ها برای هر بخش از متن، به‌جای اینکه کل پنجره از بالا به پایین نوشته شود.

کتابخانه PDCurses پشتیبانی از تخلیه صفحه را در نسخه ۲.۷ (سال ۲۰۰۵) اضافه کرد. مانند System V و ncurses5، این کتابخانه ساختار WINDOW را به صورت باینری می‌نویسد، اما فایل را با شناسه سه‌بایتی خود یعنی “PDC” و به دنبال آن یک شماره نسخه تک‌بایتی آغاز می‌کند:

“PDC\001”

تا آوریل ۲۰۱۷، NetBSD curses از توابع scr_dump و scr_restore (یا scr_init و scr_set) پشتیبانی نمی‌کند، اگرچه توابع putwin و getwin را دارد.

همانند ncurses5، تابع putwin در NetBSD تخلیه‌های خود را با یک شماره جادویی کاربردی مشخص نمی‌کند. این تابع موارد زیر را می‌نویسد:

  • نسخه‌های اصلی و فرعی (major and minor) کتابخانه مشترک curses به عنوان دو بایت نخست (برای نمونه، ۷ و ۱)،
  • به دنبال آن یک تخلیه باینری از WINDOW،
  • مقداری داده برای کاراکترهای عریض که ساختار WINDOW به آن‌ها ارجاع می‌دهد،
  • و در نهایت، خطوط متن همانند سایر پیاده‌سازی‌ها.

با فرض یک برنامه ساده که متنی را روی صفحه نمایش می‌نویسد (و برای سادگی مثال، اندازه صفحه به ۱۰×۲۰ محدود شده است):

#include <curses.h>
int
main(void)
{
    putenv("LINES=10");
    putenv("COLUMNS=20");
    initscr();
    start_color();
    init_pair(1, COLOR_WHITE, COLOR_BLUE);
    init_pair(2, COLOR_RED, COLOR_BLACK);
    bkgd(COLOR_PAIR(1));
    move(4, 5);
    attron(A_BOLD);
    addstr("Hello");
    move(5, 5);
    attroff(A_BOLD);
    attrset(A_REVERSE | COLOR_PAIR(2));
    addstr("World!");
    refresh();
    scr_dump("foo.out");
    endwin();
    return 0;
}

هنگام اجرا با استفاده از ncurses6، خروجی به شکل زیر خواهد بود:

\210\210\210\210ncurses 6.0.20170415
_cury=5
_curx=11
_maxy=9
_maxx=19
_flags=14
_attrs=\{REVERSE|C2}
flag=_idcok
_delay=-1
_regbottom=9
_bkgrnd=\{NORMAL|C1}\s
rows:
1:\{NORMAL|C1}\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
2:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
3:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
4:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
5:\s\s\s\s\s\{BOLD}Hello\{NORMAL}\s\s\s\s\s\s\s\s\s\s
6:\s\s\s\s\s\{REVERSE|C2}World!\{NORMAL|C1}\s\s\s\s\s\s\s\s\s
7:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
8:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
9:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s
10:\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s\s

چهار توالی اسکیپ هشت‌هشتی نخست در واقع کاراکترهای غیرقابل‌چاپ هستند، در حالی که بقیه فایل از متن قابل چاپ تشکیل شده است. ممکن است توجه کنید که:

  • مقادیر واقعی جفت‌رنگ‌ها (color pairs) در فایل نوشته نمی‌شوند.
  • تمام کاراکترها به شکل قابل چاپ نشان داده می‌شوند؛ فاصله‌ها به صورت “\s” هستند تا نادیده گرفته نشوند.
  • ویژگی‌ها داخل آکولادهای اسکیپ‌شده نوشته می‌شوند، مانند “\{BOLD}”، و ممکن است شامل یک جفت‌رنگ (در این مثال C1 یا C2) باشند.
  • پارامترهای موجود در هدر تنها در صورتی نوشته می‌شوند که مقدار آن‌ها غیر صفر باشد. هنگام خواندن مجدد، ترتیب آن‌ها اهمیتی ندارد.

اجرای همان برنامه با کتابخانه Solaris xpg4 curses چنین تخلیه‌ای را نتیجه می‌دهد:

MAX=10,20
BEG=0,0
SCROLL=0,10
VMIN=1
VTIME=0
FLAGS=0x1000
FG=0,0
BG=0,0,
0,0,0,1,
0,19,0,0,
1,0,0,1,
1,19,0,0,
2,0,0,1,
2,19,0,0,
3,0,0,1,
3,19,0,0,
4,0,0,1,
4,5,0x20,0,Hello
4,10,0,1,
4,19,0,0,
5,0,0,1,
5,5,0x4,2,World!
5,11,0,1,
5,19,0,0,
6,0,0,1,
6,19,0,0,
7,0,0,1,
7,19,0,0,
8,0,0,1,
8,19,0,0,
9,0,0,1,
9,19,0,0,
CUR=11,5

تابع getwin در سولاریس نیازمند آن است که تمام پارامترها موجود باشند و به همان ترتیب قرار گیرند. کتابخانه xpg4 curses از قابلیت bce (back color erase یا پاک کردن با رنگ پس‌زمینه) اطلاعی ندارد و رنگ پس‌زمینه پنجره را رنگ‌آمیزی نمی‌کند.

از سوی دیگر، کتابخانه SVr4 curses درباره رنگ پس‌زمینه آگاهی دارد. با این حال، تخلیه‌های صفحه آن به صورت باینری است. تخلیه متناظر در زیر آمده است (با استفاده از “od -t x1”):

0000000 1c 01 c3 d6 f3 58 05 00 0b 00 0a 00 14 00 00 00
0000020 00 00 02 00 00 00 00 00 00 00 00 00 00 00 00 00
0000040 00 00 b8 1a 06 08 cc 1a 06 08 00 00 09 00 10 00
0000060 00 00 00 80 00 00 20 00 00 00 ff ff ff ff 00 00
0000100 ff ff ff ff 00 00 00 00 20 80 00 00 20 80 00 00
0000120 20 80 00 00 20 80 00 00 20 80 00 00 20 80 00 00
*
0000620 20 80 00 00 20 80 00 00 20 80 00 00 48 80 00 04
0000640 65 80 00 04 6c 80 00 04 6c 80 00 04 6f 80 00 04
0000660 20 80 00 00 20 80 00 00 20 80 00 00 20 80 00 00
*
0000740 20 80 00 00 20 80 00 00 20 80 00 00 57 00 81 00
0000760 6f 00 81 00 72 00 81 00 6c 00 81 00 64 00 81 00
0001000 21 00 81 00 20 80 00 00 20 80 00 00 20 80 00 00
0001020 20 80 00 00 20 80 00 00 20 80 00 00 20 80 00 00
*
0001540 20 80 00 00 20 80 00 00 00 00 f6 d1 01 00 f6 d1
0001560 08 00 00 00 40 00 00 00 00 00 00 00 00 00 00 07
0001600 00 04 00 01 00 01 00 00 00 01 00 00 00 00 00 00
0001620 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0002371

توماس ای. دیکی (Thomas E. Dickey)
قالب گسترش‌یافته تخلیه صفحه برای ncurses 6.0 (سال ۲۰۱۵)

اریک اس. ریموند (Eric S. Raymond)
ویژگی تخلیه صفحه در ncurses 1.9.2d (سال ۱۹۹۵)

scr_dump(3NCURSES), util(3NCURSES)

2025-01-18 ncurses 6.5