main.cc 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821
  1. // Copyright (C) 2003 Mooffie <mooffie@typo.co.il>
  2. //
  3. // This program is free software; you can redistribute it and/or modify
  4. // it under the terms of the GNU General Public License as published by
  5. // the Free Software Foundation; either version 2 of the License, or
  6. // (at your option) any later version.
  7. //
  8. // This program is distributed in the hope that it will be useful,
  9. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  10. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  11. // GNU General Public License for more details.
  12. //
  13. // You should have received a copy of the GNU General Public License
  14. // along with this program; if not, write to the Free Software
  15. // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
  16. #include <config.h>
  17. // Baruch says to put io.h first.
  18. #include "io.h" // get_cfg_filename
  19. #include "pathnames.h"
  20. #include "terminal.h"
  21. #include "editor.h"
  22. #include "themes.h"
  23. #include "directvect.h"
  24. #include "dbg.h"
  25. #include <string.h>
  26. #include <stdio.h>
  27. #include <stdlib.h> // strtol
  28. #include <ctype.h> // isspace
  29. #include <unistd.h> // getopt
  30. #ifdef HAVE_GETOPT_LONG
  31. # include <getopt.h>
  32. #endif
  33. #ifdef HAVE_LOCALE_H
  34. # include <locale.h>
  35. #endif
  36. typedef DirectVector<char *> ArgsList;
  37. static int get_num(const char *optname, const u8string &arg, int min, int max)
  38. {
  39. char *endptr;
  40. int value = strtol(arg.c_str(), &endptr, 10);
  41. if (*endptr != '\0' || value < min || value > max)
  42. fatal(_("Invalid argument for option `%s'. "
  43. "Valid argument is a numeric value from %d to %d\n"),
  44. optname, min, max);
  45. return value;
  46. }
  47. static bool get_bool(const char *optname, const u8string &arg)
  48. {
  49. bool result = false;
  50. if (arg == "on" || arg == "yes" || arg == "true")
  51. result = true;
  52. else if (arg == "off" || arg == "no" || arg == "false")
  53. result = false;
  54. else
  55. fatal(_("Invalid argument for option `%s'. "
  56. "Valid argument is either `on' or `off'.\n"),
  57. optname);
  58. return result;
  59. }
  60. static void help()
  61. {
  62. printf(_("Usage: %s [options] [[+LINE] file]\n"), PACKAGE);
  63. printf(_("\nText display:\n"
  64. " -a, --dir-algo WORD Use the WORD algorithm in determining\n"
  65. " the base direction (aka \"paragraph\n"
  66. " embedding level\") of each paragraph:\n"
  67. " `unicode', `contextual-strong',\n"
  68. " `contextual-rtl', `ltr', `rtl'\n"
  69. " (default: `contextual-rtl')\n"
  70. " -D, --bidi BOOL Enable/disable BiDi\n"
  71. " -m, --maqaf WORD How to display the Hebrew makaf:\n"
  72. " `asis', `ascii', `highlight'\n"
  73. " (default: `highlight')\n"
  74. " -P, --points WORD How to display Hebrew/Arabic points:\n"
  75. " `off', `transliterate', `asis'\n"
  76. " (default: `transliterate')\n"
  77. " -M, --show-formatting BOOL Use ASCII characters to represent BiDi\n"
  78. " formatting codes, paragraph endings and\n"
  79. " tabs (default: on)\n"
  80. " -A, --arabic-shaping BOOL Use contextual presentation forms to\n"
  81. " display arabic\n"
  82. " -T, --tabsize COLS Set tab size to COLS (default: 8)\n"
  83. " (synonyms: --tab-width, --tab-size)\n"
  84. " -W, --wrap WORD Set wrap policy to:\n"
  85. " `off', `atwhitespace', `anywhere'\n"
  86. " (default: `atwhitespace')\n"
  87. " -Q, --scrollbar WORD Whether and where to display a scrollbar:\n"
  88. " `none', `left', `right'\n"
  89. " (default: `none')\n"
  90. " -G, --syntax BOOL Auto-detect syntax (for highlighting)\n"
  91. " (default: on)\n"
  92. " -U, --underline BOOL Highlight *text* and _text_\n"
  93. " (default: on)\n"
  94. " -g, --theme FILE Theme to use. FILE should be just\n"
  95. " the base file name, with no directory\n"
  96. " component.\n"
  97. " (e.g.: --theme green.thm)\n"));
  98. printf(_("\nEditing:\n"
  99. " -i, --auto-indent BOOL Automatically indent new lines\n"
  100. " -j, --auto-justify BOOL Automatically justify long lines\n"
  101. " -J, --justification-column COLS\n"
  102. " Set justification column to COLS\n"
  103. " (default: 72)\n"
  104. " -e, --rfc2646-trailing-space BOOL\n"
  105. " Keep a trailing space on each line when\n"
  106. " justifying paragraphs (default: on)\n"
  107. " -k, --key-for-key-undo BOOL Allow user to undo discrete keys\n"
  108. " (default: off)\n"
  109. " -u, --undo-size SIZE Limit undo stack to SIZE kilo-bytes\n"
  110. " (default: 50k)\n"
  111. " -q, --smart-typing BOOL Replace some plain ASCII characters with\n"
  112. " typographical ones.\n"
  113. ));
  114. printf(_("\nFiles:\n"
  115. " -f, --default-file-encoding ENC\n"
  116. " Set default file encoding to ENC\n"
  117. " -F, --file-encoding ENC Load the file (specified at the command\n"
  118. " line) using the ENC encoding\n"
  119. " -S, --suffix SFX Set file backup extension. Set to\n"
  120. " empty string if you don't want backup.\n"
  121. " (default: read the SIMPLE_BACKUP_SUFFIX\n"
  122. " environment variable if exists.\n"
  123. " If it doesn't, use \"~\")\n"));
  124. printf(_("\nTerminal capabilities:\n"
  125. " -b, --bw BOOL Don't use colors\n"
  126. " -B, --big-cursor BOOL Use a big cursor in the console, if possible\n"
  127. " -C, --combining-term BOOL Assume the terminal is capable of displaying\n"
  128. " combining characters and wide (Asian)\n"
  129. " characters\n"
  130. " -H, --iso88598-term BOOL Assume the terminal uses the ISO-8859-8\n"
  131. " encoding (only when not using wide-curses).\n"
  132. " -Y, --graphical-boxes WORD Box characters to use for the pulldown menu\n"
  133. " ans the scrollbar. Valid options:\n"
  134. " `ascii', `graphical', `auto'\n"
  135. " (default: `auto', which means that if the\n"
  136. " DISPLAY environment variable is\n"
  137. " set then use graphical chars)\n"));
  138. printf(_("\nSpeller:\n"
  139. " -Z, --speller-cmd CMD The speller command\n"
  140. " (default: \"ispell -a\")\n"
  141. " -X, --speller-encoding ENC The encoding with which to\n"
  142. " communicate with the speller.\n"
  143. " (default: ISO-8859-1)\n"
  144. " (if hspell is found, and no speller command is specified, Geresh\n"
  145. " will use it using the correct configuration automatically.)\n"));
  146. printf(_("\nLog2Vis:\n"
  147. " -p, --log2vis log2vis mode.\n"
  148. " -E, --log2vis-options OPTS The option argument OPTS may include:\n"
  149. " `bdo' - to contain the line between\n"
  150. " LRO and PDF marks.\n"
  151. " `nopad' - do not pad RTL lines on\n"
  152. " the left.\n"
  153. " `engpad' - pad LTR lines on the\n"
  154. " right.\n"
  155. " `emph[:glyph[:marker]]' - turn on\n"
  156. " underlining.\n"
  157. " -t, --log2vis-output-encoding ENC\n"
  158. " Set output encoding for log2vis\n"
  159. " (default: the encoding in which the\n"
  160. " file was read.)\n"
  161. " -w NUM Wrap paragraphs at the NUM'th column.\n"
  162. " use `-w0' to turn wrapping off.\n"
  163. " (default: use the COLUMNS environment\n"
  164. " variable, or 80)\n"));
  165. printf(_("\nMiscellaneous:\n"
  166. " -x, --extrnal-editor CMD External editor\n"
  167. " -c, --show-cursor-position BOOL\n"
  168. " Constantly display the cursor coordinates\n"
  169. //" -n, --show-numbers BOOL Show line numbers\n"
  170. " -v, -R, --read-only Read-only mode\n"
  171. " -s, --scroll-step LINES Set scroll-step to LINES lines\n"
  172. " (default: 1)\n"
  173. " -L, --visual-cursor BOOL Visual cursor movement\n"
  174. " (default: off)\n"
  175. " +LINE Go to line LINE\n"
  176. " -V, --version Print version info and editor capabilities\n"
  177. " -h, --help Print usage information\n"));
  178. printf(_("\nPlease read the User Manual for more information.\n"));
  179. exit(0);
  180. }
  181. static void parse_rc_line(ArgsList &arguments, const char *s)
  182. {
  183. const char *token_start = NULL;
  184. bool in_quote = false;
  185. if (!s || *s == '#')
  186. return;
  187. do {
  188. if (*s && !isspace(*s) && !token_start) {
  189. // starting a new token
  190. token_start = s;
  191. }
  192. if (*s == '\'' || *s == '\"')
  193. in_quote = !in_quote;
  194. if (token_start && ((isspace(*s) && !in_quote) || !*s)) {
  195. // we've found a token.
  196. // allocate memory for it and append it
  197. // to the argument list.
  198. char *param = new char[s - token_start + 1];
  199. arguments.push_back(param);
  200. // we don't preserve the quoting characters.
  201. for (const char *tp = token_start; tp < s; tp++)
  202. if (*tp != '\'' && *tp != '\"')
  203. *param++ = *tp;
  204. *param = '\0';
  205. token_start = NULL;
  206. }
  207. } while (*s++);
  208. }
  209. static bool parse_rc_file(ArgsList &arguments, const char *filename)
  210. {
  211. #define MAX_LINE_LEN 1024
  212. FILE *fp;
  213. if ((fp = fopen(filename, "r")) != NULL) {
  214. DBG(1, ("Reading rc file %s\n", filename));
  215. char line[MAX_LINE_LEN];
  216. while (fgets(line, MAX_LINE_LEN, fp)) {
  217. if (strchr(line, '#'))
  218. *(strchr(line, '#')) = '\0';
  219. parse_rc_line(arguments, line);
  220. }
  221. fclose(fp);
  222. return true;
  223. } else {
  224. return false;
  225. }
  226. #undef MAX_LINE_LEN
  227. }
  228. int main(int argc, char *argv[])
  229. {
  230. set_debug_level(getenv("GERESH_DEBUG_LEVEL")
  231. ? atoi(getenv("GERESH_DEBUG_LEVEL")) : 0);
  232. DBG(1, ("\n\n----starting----\n\n"));
  233. #ifdef HAVE_SETLOCALE
  234. if (!setlocale(LC_ALL, ""))
  235. fatal(_("setlocale() failed! Please check your environment variables "
  236. "LC_ALL, LC_CTYPE, LANG, etc.\n"));
  237. #endif
  238. terminal::determine_locale();
  239. #ifdef USE_GETTEXT
  240. // We enable gettext() only in the UTF-8 locale.
  241. // That's because gettext() returns text encoded in the locale,
  242. // whereas all the functions in this app expect UTF-8 text.
  243. // I'm not going to "fix" this -- UTF-8 locales are the way to go!
  244. //
  245. // UPDATE: I can use bind_textdomain_codeset()
  246. if (terminal::is_utf8) {
  247. bindtextdomain(PACKAGE, LOCALEDIR);
  248. textdomain(PACKAGE);
  249. }
  250. #endif
  251. /*
  252. * Step 1.
  253. *
  254. * Build a new argv, which contains arguments read from the RC file,
  255. * from the command line and from the environment variable $PACKAGE_ARGS.
  256. *
  257. */
  258. ArgsList arguments;
  259. arguments.push_back(PACKAGE); // push argv[0] (our program name)
  260. // Read arguments from the RC file.
  261. // first, read the RC file pointed to by $PACKAGE_RC.
  262. // if that fails, read the user's personal RC file, and
  263. // if that fails too, read the system wide RC file.
  264. if (!(getenv(PACKAGE "_RC")
  265. && parse_rc_file(arguments, get_cfg_filename(getenv(PACKAGE "_RC")))))
  266. {
  267. if (!parse_rc_file(arguments, get_cfg_filename(USER_RC_FILE)))
  268. parse_rc_file(arguments, get_cfg_filename(SYSTEM_RC_FILE));
  269. }
  270. // append the original command line arguments
  271. arguments.insert(arguments.end(), argv + 1, argv + argc);
  272. // and finally append all arguments in $PACKAGE_ARGS
  273. if (getenv(PACKAGE "_ARGS"))
  274. parse_rc_line(arguments, getenv(PACKAGE "_ARGS"));
  275. // the standard requires that argv[argc] == NULL
  276. arguments.push_back(NULL);
  277. argv = arguments.begin();
  278. argc = arguments.size() - 1;
  279. for (int i = 0; i < argc; i++) {
  280. DBG(1, ("[cmd: %s]\n", argv[i]));
  281. }
  282. /*
  283. * Step 2.
  284. *
  285. * Parse all the arguments using getopt().
  286. *
  287. */
  288. // The following variables hold the values parsed from the
  289. // arguments. We initialize them to default values.
  290. bool auto_justify_flag = false;
  291. bool auto_indent_flag = false;
  292. bool enable_bidi = true;
  293. bool show_formatting_flag = true;
  294. bool show_cursor_position_flag = false;
  295. bool show_numbers_flag = false; // TODO
  296. bool read_only_flag = false;
  297. int undo_size = 50;
  298. bool key_for_key_undo_flag = false;
  299. bool combining_term_flag = false;
  300. bool combining_term_flag_specified = false;
  301. bool iso88598_term_flag = false;
  302. bool big_cursor_flag = false;
  303. bool arabic_shaping_flag = false;
  304. bool bw_flag = false;
  305. int tab_width = 8;
  306. int justification_column = 72;
  307. int scroll_step = 1;
  308. bool smart_typing_flag = false;
  309. bool rfc2646_trailing_space_flag = true;
  310. bool do_log2vis = false;
  311. int non_interactive_text_width = 80;
  312. EditBox::WrapType
  313. wrap_type = EditBox::wrpAtWhiteSpace;
  314. diralgo_t
  315. dir_algo = algoContextRTL;
  316. EditBox::rtl_nsm_display_t rtl_nsm = EditBox::rtlnsmTransliterated;
  317. EditBox::maqaf_display_t maqaf = EditBox::mqfHighlighted;
  318. Editor::scrollbar_pos_t scrollbar_pos = Editor::scrlbrNone;
  319. const char
  320. *file_encoding = NULL;
  321. const char
  322. *default_file_encoding = NULL;
  323. const char
  324. *log2vis_output_encoding = NULL;
  325. const char
  326. *log2vis_options = NULL;
  327. const char
  328. *backup_suffix = getenv("SIMPLE_BACKUP_SUFFIX")
  329. ? getenv("SIMPLE_BACKUP_SUFFIX") : "~";
  330. bool
  331. print_version_flag = false;
  332. const char
  333. *speller_cmd = ""; // "ispell -a";
  334. const char
  335. *speller_encoding = ""; // "ISO-8859-1";
  336. const char
  337. *external_editor = "";
  338. const char
  339. *theme = NULL;
  340. bool syntax_auto_detection = true;
  341. bool underline = true;
  342. bool visual_cursor_movement = false;
  343. enum { boxesGraphical, boxesAscii, boxesAuto } graphical_boxes = boxesAuto;
  344. #ifdef HAVE_GETOPT_LONG
  345. static struct option long_options[] = {
  346. { "tab-width", 1, 0, 'T' },
  347. { "tabwidth", 1, 0, 'T' },
  348. { "tab-size", 1, 0, 'T' },
  349. { "tabsize", 1, 0, 'T' },
  350. { "justification-column", 1, 0, 'J' },
  351. { "rfc2646-trailing-space", 1, 0, 'e' },
  352. { "wrap", 1, 0, 'W' },
  353. { "dir-algo", 1, 0, 'a' },
  354. { "undo-size", 1, 0, 'u' },
  355. { "key-for-key-undo", 1, 0, 'k' },
  356. { "auto-justify", 1, 0, 'j' },
  357. { "auto-indent", 1, 0, 'i' },
  358. { "show-formatting",1, 0, 'M' },
  359. { "maqaf", 1, 0, 'm' },
  360. { "points", 1, 0, 'P' },
  361. { "show-cursor-position", 1, 0, 'c' },
  362. { "show-numbers", 1, 0, 'n' },
  363. { "smart-typing", 1, 0, 'q' },
  364. { "default-file-encoding", 1, 0, 'f' },
  365. { "file-encoding", 1, 0, 'F' },
  366. { "combining-term", 1, 0, 'C' },
  367. { "iso88598-term", 1, 0, 'H' },
  368. { "arabic-shaping", 1, 0, 'A' },
  369. { "read-only", 0, 0, 'R' },
  370. { "suffix", 1, 0, 'S' },
  371. { "bw", 1, 0, 'b' },
  372. { "big-cursor", 1, 0, 'B' },
  373. { "version", 0, 0, 'V' },
  374. { "help", 0, 0, 'h' },
  375. { "scroll-step", 1, 0, 's' },
  376. { "log2vis", 0, 0, 'p' },
  377. { "log2vis-output-encoding", 1, 0, 't' },
  378. { "log2vis-options", 1, 0, 'E' },
  379. { "speller-cmd", 1, 0, 'Z' },
  380. { "speller-encoding", 1, 0, 'X' },
  381. { "graphical-boxes", 1, 0, 'Y' },
  382. { "scrollbar", 1, 0, 'Q' },
  383. { "bidi", 1, 0, 'D' },
  384. { "syntax", 1, 0, 'G' },
  385. { "underline", 1, 0, 'U' },
  386. { "visual-cursor", 1, 0, 'L' },
  387. { "theme", 1, 0, 'g' },
  388. { "external-editor", 1, 0, 'x' },
  389. {0, 0, 0, 0}
  390. };
  391. #endif
  392. if (getenv("COLUMNS"))
  393. non_interactive_text_width = atoi(getenv("COLUMNS"));
  394. const char *short_options = "T:e:J:W:w:a:A:k:S:s:u:j:i:P:M:m:c:n:q:f:F:C:H:RvB:b:Vhpt:E:Z:X:Y:Q:D:G:g:U:L:x:";
  395. int c;
  396. #ifdef HAVE_GETOPT_LONG
  397. int long_idx = -1;
  398. while ((c = getopt_long(argc, argv, short_options,
  399. long_options, &long_idx)) != -1) {
  400. #else
  401. while ((c = getopt(argc, argv, short_options)) != -1) {
  402. #endif
  403. u8string optname, arg;
  404. #ifdef HAVE_GETOPT_LONG
  405. if (long_idx != -1) {
  406. optname = "--";
  407. optname += long_options[long_idx].name;
  408. } else
  409. #endif
  410. {
  411. optname = "-";
  412. optname += (char)c;
  413. }
  414. arg = optarg ? optarg : "";
  415. #define GET_BOOL() get_bool(optname.c_str(), arg)
  416. #define GET_NUM(min, max) get_num(optname.c_str(), arg, min, max)
  417. switch (c) {
  418. case 'j': auto_justify_flag = GET_BOOL(); break;
  419. case 'i': auto_indent_flag = GET_BOOL(); break;
  420. case 'M': show_formatting_flag = GET_BOOL(); break;
  421. case 'c': show_cursor_position_flag = GET_BOOL(); break;
  422. case 'n': show_numbers_flag = GET_BOOL(); break;
  423. case 'q': smart_typing_flag = GET_BOOL(); break;
  424. case 'C':
  425. combining_term_flag_specified = true;
  426. combining_term_flag = GET_BOOL();
  427. break;
  428. case 'H':
  429. #ifdef HAVE_WIDE_CURSES
  430. fatal(_("The `%s' option is now valid only when NOT "
  431. "compiling Geresh against wide-curses. (Why do "
  432. "you want to use it?)\n"),
  433. optname.c_str());
  434. #endif
  435. iso88598_term_flag = GET_BOOL();
  436. break;
  437. case 'b': bw_flag = GET_BOOL(); break;
  438. case 'A': arabic_shaping_flag = GET_BOOL(); break;
  439. case 'B': big_cursor_flag = GET_BOOL(); break;
  440. case 'k': key_for_key_undo_flag = GET_BOOL(); break;
  441. case 'R':
  442. case 'v':
  443. read_only_flag = true;
  444. break;
  445. case 'T': tab_width = GET_NUM(1, 80); break;
  446. case 'J': justification_column = GET_NUM(1, 999999); break;
  447. case 'e': rfc2646_trailing_space_flag = GET_BOOL(); break;
  448. case 'u': undo_size = GET_NUM(0, 999); break;
  449. case 's': scroll_step = GET_NUM(1, 999); break;
  450. case 'D': enable_bidi = GET_BOOL(); break;
  451. case 'G': syntax_auto_detection = GET_BOOL(); break;
  452. case 'U': underline = GET_BOOL(); break;
  453. case 'L': visual_cursor_movement = GET_BOOL(); break;
  454. case 'W':
  455. if (arg == "off")
  456. wrap_type = EditBox::wrpOff;
  457. else if (arg == "atwhitespace")
  458. wrap_type = EditBox::wrpAtWhiteSpace;
  459. else if (arg == "anywhere")
  460. wrap_type = EditBox::wrpAnywhere;
  461. else
  462. fatal(_("invalid argument `%s' for `%s'\n"
  463. "Valid arguments are:\n"
  464. "%s"),
  465. optarg, optname.c_str(),
  466. _(" - `off'\n"
  467. " - `atwhitespace'\n"
  468. " - `anywhere'\n"));
  469. break;
  470. case 'a':
  471. if (arg == "unicode")
  472. dir_algo = algoUnicode;
  473. else if (arg == "contextual-strong")
  474. dir_algo = algoContextStrong;
  475. else if (arg == "contextual-rtl")
  476. dir_algo = algoContextRTL;
  477. else if (arg == "ltr")
  478. dir_algo = algoForceLTR;
  479. else if (arg == "rtl")
  480. dir_algo = algoForceRTL;
  481. else
  482. fatal(_("invalid argument `%s' for `%s'\n"
  483. "Valid arguments are:\n"
  484. "%s"),
  485. optarg, optname.c_str(),
  486. _(" - `unicode'\n"
  487. " - `contextual-strong'\n"
  488. " - `contextual-rtl'\n"
  489. " - `ltr'\n"
  490. " - `rtl'\n"));
  491. break;
  492. case 'm':
  493. if (arg == "asis")
  494. maqaf = EditBox::mqfAsis;
  495. else if (arg == "ascii")
  496. maqaf = EditBox::mqfTransliterated;
  497. else if (arg == "highlight")
  498. maqaf = EditBox::mqfHighlighted;
  499. else
  500. fatal(_("invalid argument `%s' for `%s'\n"
  501. "Valid arguments are:\n"
  502. "%s"),
  503. optarg, optname.c_str(),
  504. _(" - `asis'\n"
  505. " - `ascii'\n"
  506. " - `highlight'\n"));
  507. break;
  508. case 'P':
  509. if (arg == "off")
  510. rtl_nsm = EditBox::rtlnsmOff;
  511. else if (arg == "transliterate")
  512. rtl_nsm = EditBox::rtlnsmTransliterated;
  513. else if (arg == "asis")
  514. rtl_nsm = EditBox::rtlnsmAsis;
  515. else
  516. fatal(_("invalid argument `%s' for `%s'\n"
  517. "Valid arguments are:\n"
  518. "%s"),
  519. optarg, optname.c_str(),
  520. _(" - `off'\n"
  521. " - `transliterate'\n"
  522. " - `asis'\n"));
  523. break;
  524. case 'Y':
  525. if (arg == "graphical")
  526. graphical_boxes = boxesGraphical;
  527. else if (arg == "ascii")
  528. graphical_boxes = boxesAscii;
  529. else if (arg == "auto")
  530. graphical_boxes = boxesAuto;
  531. else
  532. fatal(_("invalid argument `%s' for `%s'\n"
  533. "Valid arguments are:\n"
  534. "%s"),
  535. optarg, optname.c_str(),
  536. _(" - `graphical'\n"
  537. " - `ascii'\n"
  538. " - `auto'\n"));
  539. break;
  540. case 'Q':
  541. if (arg == "none")
  542. scrollbar_pos = Editor::scrlbrNone;
  543. else if (arg == "left")
  544. scrollbar_pos = Editor::scrlbrLeft;
  545. else if (arg == "right")
  546. scrollbar_pos = Editor::scrlbrRight;
  547. else
  548. fatal(_("invalid argument `%s' for `%s'\n"
  549. "Valid arguments are:\n"
  550. "%s"),
  551. optarg, optname.c_str(),
  552. _(" - `none'\n"
  553. " - `left'\n"
  554. " - `right'\n"));
  555. break;
  556. case 'F': file_encoding = optarg; break;
  557. case 'f': default_file_encoding = optarg; break;
  558. case 't': log2vis_output_encoding = optarg; break;
  559. case 'S': backup_suffix = optarg; break;
  560. case 'p':
  561. do_log2vis = true;
  562. arabic_shaping_flag = true;
  563. show_formatting_flag = false;
  564. rtl_nsm = EditBox::rtlnsmAsis;
  565. break;
  566. case 'E': log2vis_options = optarg; break;
  567. case 'w': non_interactive_text_width = GET_NUM(0, 9999); break;
  568. case 'Z': speller_cmd = optarg; break;
  569. case 'X': speller_encoding = optarg; break;
  570. case 'g': theme = optarg; break;
  571. case 'x': external_editor = optarg; break;
  572. case 'V': print_version_flag = true; break;
  573. case 'h': help(); break;
  574. case '?':
  575. fatal(NULL);
  576. break;
  577. }
  578. #ifdef HAVE_GETOPT_LONG
  579. long_idx = -1;
  580. #endif
  581. }
  582. #undef GET_BOOL
  583. #undef GET_NUM
  584. if (non_interactive_text_width == 0)
  585. wrap_type = EditBox::wrpOff;
  586. /*
  587. * Step 3.
  588. *
  589. * Initialize the terminal.
  590. *
  591. */
  592. if (iso88598_term_flag) {
  593. terminal::is_utf8 = false;
  594. terminal::force_iso88598 = true;
  595. terminal::is_fixed = true;
  596. }
  597. if (combining_term_flag_specified) {
  598. terminal::is_fixed = !combining_term_flag;
  599. }
  600. #ifndef HAVE_WIDE_CURSES
  601. if (terminal::is_utf8)
  602. fatal(_("Terminal locale is UTF-8, but %s was not compiled with a "
  603. "curses library that supports wide characters (ncursesw). "
  604. "Please read the INSTALL document that accompanies Geresh "
  605. "to get more information.\n"), PACKAGE);
  606. #endif
  607. // the -V option ("print version") is very useful when we want to
  608. // find out what the program thinks our terminal capabilities are.
  609. if (print_version_flag) {
  610. printf(_("%s version %s\n"), PACKAGE, VERSION);
  611. #ifdef HAVE_WIDE_CURSES
  612. printf(_("Compiled with wide-curses.\n"));
  613. #endif
  614. printf(_("\nTerminal encoding:\n%s, %s\n"),
  615. terminal::is_utf8
  616. ? "UTF-8"
  617. : "8-bit",
  618. terminal::is_fixed
  619. ? _("cannot handle combining/wide characters")
  620. : _("can handle combining/wide characters"));
  621. if (terminal::force_iso88598)
  622. printf(_("I'll treat this terminal as ISO-8859-8\n"));
  623. printf(_("\nFiles I can use:\n"));
  624. const char * files[] = {
  625. USER_RC_FILE,
  626. USER_TRANSTBL_FILE,
  627. USER_REPRTBL_FILE,
  628. USER_ALTKBDTBL_FILE,
  629. USER_MANUAL_FILE,
  630. USER_UNICODE_DATA_FILE,
  631. USER_THEMES_DIR,
  632. SYSTEM_RC_FILE,
  633. SYSTEM_TRANSTBL_FILE,
  634. SYSTEM_REPRTBL_FILE,
  635. SYSTEM_ALTKBDTBL_FILE,
  636. SYSTEM_MANUAL_FILE,
  637. SYSTEM_UNICODE_DATA_FILE,
  638. SYSTEM_THEMES_DIR,
  639. NULL
  640. };
  641. int i = 0;
  642. while (files[i])
  643. printf("%s\n", get_cfg_filename(files[i++]));
  644. exit(0);
  645. }
  646. if (!do_log2vis) {
  647. terminal::init();
  648. if (bw_flag)
  649. terminal::is_color = false;
  650. if (graphical_boxes != boxesAuto)
  651. terminal::graphical_boxes = (graphical_boxes == boxesGraphical);
  652. ThemeError theme_error;
  653. bool rslt;
  654. if (!theme || !terminal::is_color)
  655. rslt = load_default_theme(theme_error);
  656. else
  657. rslt = load_theme(theme, theme_error);
  658. if (!rslt) {
  659. terminal::finish();
  660. fatal(_("Can't load theme: %s\n"), theme_error.format().c_str());
  661. }
  662. } else {
  663. terminal::is_fixed = false;
  664. terminal::is_utf8 = true;
  665. }
  666. /*
  667. * Step 3.
  668. *
  669. * Instantiate and initialize an Editor object.
  670. * Load the file specified on the command line.
  671. *
  672. */
  673. Editor bde;
  674. bde.set_tab_width(tab_width);
  675. bde.set_justification_column(justification_column);
  676. bde.set_rfc2646_trailing_space(rfc2646_trailing_space_flag);
  677. bde.set_wrap_type(wrap_type);
  678. bde.set_dir_algo(dir_algo);
  679. bde.set_scroll_step(scroll_step);
  680. bde.set_maqaf_display(maqaf);
  681. bde.set_rtl_nsm_display(rtl_nsm);
  682. bde.set_backup_suffix(backup_suffix);
  683. bde.set_smart_typing(smart_typing_flag);
  684. bde.set_undo_size_limit(undo_size * 1024);
  685. bde.set_key_for_key_undo(key_for_key_undo_flag);
  686. bde.set_read_only(read_only_flag);
  687. bde.set_speller_cmd(speller_cmd);
  688. bde.set_speller_encoding(speller_encoding);
  689. bde.adjust_speller_cmd();
  690. bde.set_external_editor(external_editor);
  691. bde.set_scrollbar_pos(scrollbar_pos);
  692. bde.enable_bidi(enable_bidi);
  693. bde.set_syntax_auto_detection(syntax_auto_detection);
  694. bde.set_underline(underline);
  695. bde.set_visual_cursor_movement(visual_cursor_movement);
  696. if (default_file_encoding)
  697. bde.set_default_encoding(default_file_encoding);
  698. if (arabic_shaping_flag)
  699. bde.toggle_arabic_shaping();
  700. if (auto_indent_flag)
  701. bde.toggle_auto_indent();
  702. if (auto_justify_flag)
  703. bde.toggle_auto_justify();
  704. if (!show_formatting_flag)
  705. bde.toggle_formatting_marks();
  706. if (show_cursor_position_flag)
  707. bde.toggle_cursor_position_report();
  708. #ifdef HAVE_CURS_SET
  709. if (!do_log2vis && big_cursor_flag)
  710. bde.set_big_cursor(true);
  711. #endif
  712. // Load file
  713. const char *filename = NULL;
  714. int go_to_line = 0;
  715. for (int i = optind; i < argc; i++) {
  716. if (*argv[i] == '+')
  717. go_to_line = atol(argv[i]);
  718. else
  719. filename = argv[i];
  720. }
  721. if (do_log2vis) {
  722. bde.set_non_interactive_text_width(non_interactive_text_width);
  723. if (filename) {
  724. bde.load_file(filename, file_encoding);
  725. if (bde.is_new()) {
  726. // a crude method to print an error message
  727. // when the file does not exist.
  728. bde.insert_file(filename, file_encoding);
  729. }
  730. } else {
  731. bde.load_file("-", file_encoding);
  732. }
  733. if (log2vis_output_encoding)
  734. bde.set_encoding(log2vis_output_encoding);
  735. } else {
  736. if (filename)
  737. bde.load_file(filename, file_encoding);
  738. if (go_to_line > 0)
  739. bde.go_to_line(go_to_line);
  740. }
  741. /*
  742. * Step 4.
  743. *
  744. * Start the event pump.
  745. *
  746. */
  747. if (!do_log2vis) {
  748. bde.exec();
  749. } else {
  750. bde.log2vis(log2vis_options);
  751. bde.save_file("-", bde.get_encoding());
  752. }
  753. if (!do_log2vis) {
  754. terminal::finish();
  755. }
  756. return 0;
  757. }