2 # include "osx_messagebox.h"
3 #elif defined(unix) && defined(HAVE_GTK2)
14 #include "music_and_sound_g.h"
25 // For the printGLError macro
28 // Set to 0 when the game wants to quit
29 static int loopvar
= 1;
31 // Reports an error to the user, using a MessageBox and stderr.
32 void report_error(const char *error_preface
, const char *error_message
)
35 // +4 = +colon +space +newline +nul
36 buf
= new char[strlen(error_preface
) + strlen(error_message
) + 4];
37 sprintf(buf
, "%s: %s\n", error_preface
, error_message
);
38 MessageBox(NULL
, buf
, "Error", MB_OK
);
39 fprintf(stderr
, "%s", buf
);
43 Either
<texture_fullid
,texture_ttfid
> renderer::screen_to_texid(int x
, int y
) {
44 const int tile
= x
* gps
.dimy
+ y
;
45 const unsigned char *s
= screen
+ tile
*4;
47 struct texture_fullid ret
;
53 // TTF text does not get the full treatment.
54 if (s
[3] == GRAPHICSTYPE_TTF
) {
55 texture_ttfid texpos
= *((unsigned int *)s
) & 0xffffff;
56 return Either
<texture_fullid
,texture_ttfid
>(texpos
);
57 } else if (s
[3] == GRAPHICSTYPE_TTFCONT
) {
58 // TTFCONT means this is a tile that does not have TTF anchored on it, but is covered by TTF.
59 // Since this may actually be stale information, we'll draw it as a blank space,
63 // Otherwise, it's a normal (graphical?) tile.
65 bold
= (s
[3] != 0) * 8;
66 fg
= (s
[1] + bold
) % 16;
70 static bool use_graphics
= init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
);
73 const long texpos
= screentexpos
[tile
];
74 const char addcolor
= screentexpos_addcolor
[tile
];
75 const unsigned char grayscale
= screentexpos_grayscale
[tile
];
76 const unsigned char cf
= screentexpos_cf
[tile
];
77 const unsigned char cbr
= screentexpos_cbr
[tile
];
82 ret
.r
= enabler
.ccolor
[cf
][0];
83 ret
.g
= enabler
.ccolor
[cf
][1];
84 ret
.b
= enabler
.ccolor
[cf
][2];
85 ret
.br
= enabler
.ccolor
[cbr
][0];
86 ret
.bg
= enabler
.ccolor
[cbr
][1];
87 ret
.bb
= enabler
.ccolor
[cbr
][2];
88 } else if (addcolor
) {
91 ret
.r
= ret
.g
= ret
.b
= 1;
92 ret
.br
= ret
.bg
= ret
.bb
= 0;
98 ret
.texpos
= enabler
.is_fullscreen() ?
99 init
.font
.large_font_texpos
[ch
] :
100 init
.font
.small_font_texpos
[ch
];
102 ret
.r
= enabler
.ccolor
[fg
][0];
103 ret
.g
= enabler
.ccolor
[fg
][1];
104 ret
.b
= enabler
.ccolor
[fg
][2];
105 ret
.br
= enabler
.ccolor
[bg
][0];
106 ret
.bg
= enabler
.ccolor
[bg
][1];
107 ret
.bb
= enabler
.ccolor
[bg
][2];
111 return Either
<texture_fullid
,texture_ttfid
>(ret
);
116 # include "renderer_curses.cpp"
118 #include "renderer_2d.hpp"
119 #include "renderer_opengl.hpp"
122 enablerst::enablerst() {
128 calculated_fps
= calculated_gfps
= frame_sum
= gframe_sum
= frame_last
= gframe_last
= 0;
129 fps
= 100; gfps
= 20;
130 fps_per_gfps
= fps
/ gfps
;
134 void renderer::display()
136 const int dimx
= init
.display
.grid_x
;
137 const int dimy
= init
.display
.grid_y
;
138 static bool use_graphics
= init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
);
139 if (gps
.force_full_display_count
) {
140 // Update the entire screen
143 Uint32
*screenp
= (Uint32
*)screen
, *oldp
= (Uint32
*)screen_old
;
146 for (int x2
=0; x2
< dimx
; x2
++) {
147 for (int y2
=0; y2
< dimy
; y2
++, ++off
, ++screenp
, ++oldp
) {
148 // We don't use pointers for the non-screen arrays because we mostly fail at the
149 // *first* comparison, and having pointers for the others would exceed register
151 // Partial printing (and color-conversion): Big-ass if.
152 if (*screenp
== *oldp
&&
153 screentexpos
[off
] == screentexpos_old
[off
] &&
154 screentexpos_addcolor
[off
] == screentexpos_addcolor_old
[off
] &&
155 screentexpos_grayscale
[off
] == screentexpos_grayscale_old
[off
] &&
156 screentexpos_cf
[off
] == screentexpos_cf_old
[off
] &&
157 screentexpos_cbr
[off
] == screentexpos_cbr_old
[off
])
159 // Nothing's changed, this clause deliberately empty
166 for (int x2
=0; x2
< dimx
; ++x2
) {
167 for (int y2
=0; y2
< dimy
; ++y2
, ++screenp
, ++oldp
) {
168 if (*screenp
!= *oldp
) {
175 if (gps
.force_full_display_count
> 0) gps
.force_full_display_count
--;
178 void renderer::cleanup_arrays() {
179 if (screen
) delete[] screen
;
180 if (screentexpos
) delete[] screentexpos
;
181 if (screentexpos_addcolor
) delete[] screentexpos_addcolor
;
182 if (screentexpos_grayscale
) delete[] screentexpos_grayscale
;
183 if (screentexpos_cf
) delete[] screentexpos_cf
;
184 if (screentexpos_cbr
) delete[] screentexpos_cbr
;
185 if (screen_old
) delete[] screen_old
;
186 if (screentexpos_old
) delete[] screentexpos_old
;
187 if (screentexpos_addcolor_old
) delete[] screentexpos_addcolor_old
;
188 if (screentexpos_grayscale_old
) delete[] screentexpos_grayscale_old
;
189 if (screentexpos_cf_old
) delete[] screentexpos_cf_old
;
190 if (screentexpos_cbr_old
) delete[] screentexpos_cbr_old
;
193 void renderer::gps_allocate(int x
, int y
) {
196 gps
.screen
= screen
= new unsigned char[x
*y
*4];
197 memset(screen
, 0, x
*y
*4);
198 gps
.screentexpos
= screentexpos
= new long[x
*y
];
199 memset(screentexpos
, 0, x
*y
*sizeof(long));
200 gps
.screentexpos_addcolor
= screentexpos_addcolor
= new char[x
*y
];
201 memset(screentexpos_addcolor
, 0, x
*y
);
202 gps
.screentexpos_grayscale
= screentexpos_grayscale
= new unsigned char[x
*y
];
203 memset(screentexpos_grayscale
, 0, x
*y
);
204 gps
.screentexpos_cf
= screentexpos_cf
= new unsigned char[x
*y
];
205 memset(screentexpos_cf
, 0, x
*y
);
206 gps
.screentexpos_cbr
= screentexpos_cbr
= new unsigned char[x
*y
];
207 memset(screentexpos_cbr
, 0, x
*y
);
209 screen_old
= new unsigned char[x
*y
*4];
210 memset(screen_old
, 0, x
*y
*4);
211 screentexpos_old
= new long[x
*y
];
212 memset(screentexpos_old
, 0, x
*y
*sizeof(long));
213 screentexpos_addcolor_old
= new char[x
*y
];
214 memset(screentexpos_addcolor_old
, 0, x
*y
);
215 screentexpos_grayscale_old
= new unsigned char[x
*y
];
216 memset(screentexpos_grayscale_old
, 0, x
*y
);
217 screentexpos_cf_old
= new unsigned char[x
*y
];
218 memset(screentexpos_cf_old
, 0, x
*y
);
219 screentexpos_cbr_old
= new unsigned char[x
*y
];
220 memset(screentexpos_cbr_old
, 0, x
*y
);
225 void renderer::swap_arrays() {
226 screen
= screen_old
; screen_old
= gps
.screen
; gps
.screen
= screen
;
227 screentexpos
= screentexpos_old
; screentexpos_old
= gps
.screentexpos
; gps
.screentexpos
= screentexpos
;
228 screentexpos_addcolor
= screentexpos_addcolor_old
; screentexpos_addcolor_old
= gps
.screentexpos_addcolor
; gps
.screentexpos_addcolor
= screentexpos_addcolor
;
229 screentexpos_grayscale
= screentexpos_grayscale_old
; screentexpos_grayscale_old
= gps
.screentexpos_grayscale
; gps
.screentexpos_grayscale
= screentexpos_grayscale
;
230 screentexpos_cf
= screentexpos_cf_old
; screentexpos_cf_old
= gps
.screentexpos_cf
; gps
.screentexpos_cf
= screentexpos_cf
;
231 screentexpos_cbr
= screentexpos_cbr_old
; screentexpos_cbr_old
= gps
.screentexpos_cbr
; gps
.screentexpos_cbr
= screentexpos_cbr
;
233 gps
.screen_limit
= gps
.screen
+ gps
.dimx
* gps
.dimy
* 4;
236 void enablerst::pause_async_loop() {
237 struct async_cmd cmd
;
238 cmd
.cmd
= async_cmd::pause
;
239 async_tobox
.write(cmd
);
243 // Wait until the previous command has been acknowledged, /or/
244 // async_loop has quit. Incidentally execute any requests in the
246 void enablerst::async_wait() {
247 if (loopvar
== 0) return;
249 bool reset_textures
= false;
251 async_frombox
.read(r
);
253 case async_msg::quit
:
256 case async_msg::complete
:
257 if (reset_textures
) {
258 puts("Resetting textures");
259 textures
.remove_uploaded_textures();
260 textures
.upload_textures();
263 case async_msg::set_fps
:
265 async_fromcomplete
.write();
267 case async_msg::set_gfps
:
269 async_fromcomplete
.write();
271 case async_msg::push_resize
:
272 override_grid_size(r
.x
, r
.y
);
273 async_fromcomplete
.write();
275 case async_msg::pop_resize
:
277 async_fromcomplete
.write();
279 case async_msg::reset_textures
:
280 reset_textures
= true;
283 puts("EMERGENCY: Unknown case in async_wait");
289 void enablerst::async_loop() {
290 async_paused
= false;
292 int total_frames
= 0;
293 int fps
= 100; // Just a thread-local copy
295 // cout << "FRAMES: " << frames << endl;
296 // Check for commands
298 bool have_cmd
= true;
300 if (async_paused
|| (async_frames
== 0 && !(enabler
.flag
& ENABLERFLAG_MAXFPS
)))
301 async_tobox
.read(cmd
);
303 have_cmd
= async_tobox
.try_read(cmd
);
304 // Obey the command, would you kindly.
307 case async_cmd::pause
:
310 async_frombox
.write(async_msg(async_msg::complete
));
312 case async_cmd::start
:
313 async_paused
= false;
317 case async_cmd::render
:
318 if (flag
& ENABLERFLAG_RENDER
) {
320 renderer
->swap_arrays();
321 if (total_frames
% 1800 == 0)
324 flag
&= ~ENABLERFLAG_RENDER
;
327 async_frombox
.write(async_msg(async_msg::complete
));
330 async_frames
+= cmd
.val
;
331 if (async_frames
> fps
*3) async_frames
= fps
*3; // Just in case
333 case async_cmd::set_fps
:
339 // Run the main-loop, maybe
340 if (!async_paused
&& (async_frames
|| (enabler
.flag
& ENABLERFLAG_MAXFPS
))) {
342 async_frombox
.write(async_msg(async_msg::quit
));
343 return; // We're done.
349 if (async_frames
< 0) async_frames
= 0;
352 SDL_NumJoysticks(); // Hook for dfhack
356 void enablerst::do_frame() {
357 // Check how long it's been, exactly
358 const Uint32 now
= SDL_GetTicks();
359 const Uint32 interval
= CLAMP(now
- last_tick
, 0, 1000); // Anything above a second doesn't count
360 // cout << last_tick << " + " << interval << " = " << now << endl;
363 // Update outstanding-frame counts
364 outstanding_frames
+= interval
* fps
/ 1000;
365 outstanding_gframes
+= interval
* gfps
/ 1000;
366 if (outstanding_gframes
> 3) {
367 outstanding_gframes
= 3;
369 // cout << outstanding_frames << " " << outstanding_gframes << endl;
371 // Update the loop's tick-counter suitably
372 if (outstanding_frames
>= 1) {
373 async_cmd
cmd(async_cmd::inc
);
374 cmd
.val
= outstanding_frames
;
375 outstanding_frames
-= cmd
.val
;
376 async_tobox
.write(cmd
);
379 // Store the current time, for things that are fine with approximations
380 enabler
.clock
= SDL_GetTicks();
382 // If it's time to render..
383 if (outstanding_gframes
>= 1
386 (!sync
|| glClientWaitSync(sync
, 0, 0) == GL_ALREADY_SIGNALED
)
390 // Get the async-loop to render_things
391 async_cmd
cmd(async_cmd::render
);
392 async_tobox
.write(cmd
);
400 outstanding_gframes
--;
403 // Sleep until the next gframe
404 if (outstanding_gframes
< 1) {
405 float fragment
= 1 - outstanding_gframes
;
406 float milliseconds
= fragment
/ gfps
* 1000;
407 // cout << milliseconds << endl;
408 SDL_Delay(milliseconds
);
412 void enablerst::eventLoop_SDL()
416 const SDL_Surface
*screen
= SDL_GetVideoSurface();
417 Uint32 mouse_lastused
= 0;
418 SDL_ShowCursor(SDL_DISABLE
);
420 // Initialize the grid
421 renderer
->resize(screen
->w
, screen
->h
);
424 Uint32 now
= SDL_GetTicks();
425 bool paused_loop
= false;
427 // Check for zoom commands
429 while (async_zoom
.try_read(zoom
)) {
430 if (overridden_grid_sizes
.size())
431 continue; // No zooming in movies
436 if (zoom
== zoom_fullscreen
)
437 renderer
->set_fullscreen();
439 renderer
->zoom(zoom
);
442 // Check for SDL events
443 while (SDL_PollEvent(&event
)) {
444 // Make sure mainloop isn't running while we're processing input
450 switch (event
.type
) {
452 // Disable mouse if it's been long enough
453 if (mouse_lastused
+ 5000 < now
) {
454 if(init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_PICTURE
)) {
455 // hide the mouse picture
456 // enabler.set_tile(0, TEXTURE_MOUSE, enabler.mouse_x, enabler.mouse_y);
458 SDL_ShowCursor(SDL_DISABLE
);
462 enabler
.add_input(event
, now
);
464 case SDL_MOUSEBUTTONDOWN
:
465 case SDL_MOUSEBUTTONUP
:
466 if (!init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_OFF
)) {
467 int isdown
= (event
.type
== SDL_MOUSEBUTTONDOWN
);
468 if (event
.button
.button
== SDL_BUTTON_LEFT
) {
469 enabler
.mouse_lbut
= isdown
;
470 enabler
.mouse_lbut_down
= isdown
;
472 enabler
.mouse_lbut_lift
= 0;
473 } else if (event
.button
.button
== SDL_BUTTON_RIGHT
) {
474 enabler
.mouse_rbut
= isdown
;
475 enabler
.mouse_rbut_down
= isdown
;
477 enabler
.mouse_rbut_lift
= 0;
479 enabler
.add_input(event
, now
);
482 case SDL_MOUSEMOTION
:
483 // Deal with the mouse hiding bit
484 mouse_lastused
= now
;
485 if(init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_PICTURE
)) {
486 // turn on mouse picture
487 // enabler.set_tile(gps.tex_pos[TEXTURE_MOUSE], TEXTURE_MOUSE,enabler.mouse_x, enabler.mouse_y);
489 SDL_ShowCursor(SDL_ENABLE
);
492 case SDL_ACTIVEEVENT
:
493 enabler
.clear_input();
494 if (event
.active
.state
& SDL_APPACTIVE
) {
495 if (event
.active
.gain
) {
496 enabler
.flag
|=ENABLERFLAG_RENDER
;
497 gps
.force_full_display_count
++;
501 case SDL_VIDEOEXPOSE
:
502 gps
.force_full_display_count
++;
503 enabler
.flag
|=ENABLERFLAG_RENDER
;
505 case SDL_VIDEORESIZE
:
506 if (is_fullscreen());
507 //errorlog << "Caught resize event in fullscreen??\n";
509 //gamelog << "Resizing window to " << event.resize.w << "x" << event.resize.h << endl << flush;
510 renderer
->resize(event
.resize
.w
, event
.resize
.h
);
513 } // switch (event.type)
516 // Update mouse state
517 if (!init
.input
.flag
.has_flag(INIT_INPUT_FLAG_MOUSE_OFF
)) {
518 int mouse_x
= -1, mouse_y
= -1, mouse_state
;
519 // Check whether the renderer considers this valid input or not, and write it to gps
520 if ((SDL_GetAppState() & SDL_APPMOUSEFOCUS
) &&
521 renderer
->get_mouse_coords(mouse_x
, mouse_y
)) {
526 if (mouse_x
!= gps
.mouse_x
|| mouse_y
!= gps
.mouse_y
||
527 mouse_state
!= enabler
.tracking_on
) {
528 // Pause rendering loop and update values
533 enabler
.tracking_on
= mouse_state
;
534 gps
.mouse_x
= mouse_x
;
535 gps
.mouse_y
= mouse_y
;
540 unpause_async_loop();
543 #if !defined(NO_FMOD)
544 // Call FMOD::System.update(). Manages a bunch of sound stuff.
550 int enablerst::loop(string cmdline
) {
551 command_line
= cmdline
;
553 // Initialize the tick counters
557 // Call DF's initialization routine
561 // Allocate a renderer
562 if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
564 renderer
= new renderer_curses();
566 report_error("PRINT_MODE", "TEXT not supported on windows");
569 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_2D
)) {
570 renderer
= new renderer_2d();
572 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_ACCUM_BUFFER
)) {
573 renderer
= new renderer_accum_buffer();
574 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_FRAME_BUFFER
)) {
575 renderer
= new renderer_framebuffer();
576 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_PARTIAL_PRINT
)) {
577 if (init
.display
.partial_print_count
)
578 renderer
= new renderer_partial();
580 renderer
= new renderer_once();
581 } else if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_VBO
)) {
582 renderer
= new renderer_vbo();
584 renderer
= new renderer_opengl();
586 renderer
= new renderer_2d();
590 // At this point we should have a window that is setup to render DF.
591 if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
596 SDL_EnableUNICODE(1);
602 // Clean up graphical resources
606 void enablerst::override_grid_size(int x
, int y
) {
607 if (SDL_ThreadID() != renderer_threadid
) {
608 // Ask the renderer to do it
609 async_msg
m(async_msg::push_resize
);
611 async_frombox
.write(m
);
612 async_fromcomplete
.read();
614 // We are the renderer; do it.
615 overridden_grid_sizes
.push(make_pair(init
.display
.grid_x
,init
.display
.grid_y
));
616 renderer
->grid_resize(x
, y
);
620 void enablerst::release_grid_size() {
621 if (SDL_ThreadID() != renderer_threadid
) {
622 async_frombox
.write(async_msg(async_msg::pop_resize
));
623 async_fromcomplete
.read();
625 if (!overridden_grid_sizes
.size()) return;
626 // FIXME: Find out whatever is causing release to be called too rarely; right now
627 // we're overriding once per movie but apparently only releasing for the last one.
629 while (overridden_grid_sizes
.size()) {
630 sz
= overridden_grid_sizes
.top();
631 overridden_grid_sizes
.pop();
633 zoom_display(zoom_resetgrid
);
637 void enablerst::zoom_display(zoom_commands command
) {
638 async_zoom
.write(command
);
641 int enablerst::calculate_fps() {
642 if (frame_timings
.size() < 50)
645 return calculated_fps
;
647 int enablerst::calculate_gfps() {
648 if (gframe_timings
.size() < 50)
651 return calculated_gfps
;
654 void enablerst::do_update_fps(queue
<int> &q
, int &sum
, int &last
, int &calc
) {
655 while (q
.size() > 50 && sum
> 10000) {
659 const int now
= SDL_GetTicks();
660 const int interval
= now
- last
;
665 calc
= q
.size() * 1000 / sum
;
668 void enablerst::clear_fps() {
669 while (frame_timings
.size())
672 frame_last
= SDL_GetTicks();
673 calculated_fps
= get_fps();
676 void enablerst::update_fps() {
677 do_update_fps(frame_timings
, frame_sum
, frame_last
, calculated_fps
);
680 void enablerst::update_gfps() {
681 do_update_fps(gframe_timings
, gframe_sum
, gframe_last
, calculated_gfps
);
684 void enablerst::set_fps(int fps
) {
685 if (SDL_ThreadID() != renderer_threadid
) {
686 async_msg
m(async_msg::set_fps
);
689 async_frombox
.write(m
);
690 async_fromcomplete
.read();
695 fps_per_gfps
= fps
/ gfps
;
696 struct async_cmd cmd
;
697 cmd
.cmd
= async_cmd::set_fps
;
699 async_tobox
.write(cmd
);
700 async_tobox
.write(async_cmd(async_cmd::start
));
704 void enablerst::set_gfps(int gfps
) {
705 if (SDL_ThreadID() != renderer_threadid
) {
706 async_msg
m(async_msg::set_gfps
);
708 async_frombox
.write(m
);
709 async_fromcomplete
.read();
714 fps_per_gfps
= fps
/ gfps
;
718 int call_loop(void *dummy
) {
719 enabler
.async_loop();
723 int main (int argc
, char* argv
[]) {
725 setlocale(LC_ALL
, "");
727 #if !defined(__APPLE__) && defined(unix) && defined(HAVE_GTK2)
729 if (getenv("DISPLAY"))
730 gtk_ok
= gtk_init_check(&argc
, &argv
);
733 // Initialise minimal SDL subsystems.
734 int retval
= SDL_Init(SDL_INIT_TIMER
);
737 report_error("SDL initialization failure", SDL_GetError());
740 enabler
.renderer_threadid
= SDL_ThreadID();
742 // Spawn simulation thread
743 SDL_CreateThread(call_loop
, NULL
);
745 init
.begin(); // Load init.txt settings
747 #if !defined(__APPLE__) && defined(unix) && defined(HAVE_GTK2)
748 if (!gtk_ok
&& !init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
)) {
749 puts("Display not found and PRINT_MODE not set to TEXT, aborting.");
752 if (init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
) &&
753 init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_USE_GRAPHICS
)) {
754 puts("Graphical tiles are not compatible with text output, sorry");
759 // Initialize video, if we /use/ video
760 retval
= SDL_InitSubSystem(init
.display
.flag
.has_flag(INIT_DISPLAY_FLAG_TEXT
) ? 0 : SDL_INIT_VIDEO
);
762 report_error("SDL initialization failure", SDL_GetError());
767 if (!init
.media
.flag
.has_flag(INIT_MEDIA_FLAG_SOUND_OFF
)) {
769 if (!musicsound
.initsound()) {
770 puts("Initializing OpenAL failed, no sound will be played");
771 init
.media
.flag
.add_flag(INIT_MEDIA_FLAG_SOUND_OFF
);
777 // Attempt to get as good a timer as possible
779 while (timeBeginPeriod(ms
) != TIMERR_NOERROR
) ms
++;
784 enabler
.load_keybindings("data/init/interface.txt");
787 for (int i
= 1; i
< argc
; ++i
) {
788 char *option
= argv
[i
];
792 //main removes quotes, unlike the winmain version, so it has to be rebuilt
807 int result
= enabler
.loop(cmdLine
);
818 char get_slot_and_addbit_uchar(unsigned char &addbit
,long &slot
,long checkflag
,long slotnum
)
820 if(checkflag
<0)return 0;
824 if(slot
>=slotnum
)return 0;
826 //FIND PROPER BIT IN THAT SLOT
827 addbit
=1<<(checkflag
%8);
832 void text_system_file_infost::initialize_info()
834 std::ifstream
fseed(filename
.c_str());
839 while(std::getline(fseed
,str
))
841 if(str
.length()>0)number
++;
847 str
="Error Initializing Text: ";
849 errorlog_string(str
);
854 void text_system_file_infost::get_text(text_infost
&text
)
860 std::ifstream
fseed(filename
.c_str());
865 int num
=trandom(number
);
867 //SKIP AHEAD TO THE RIGHT SPOT
870 std::getline(fseed
,str
);
874 //PROCESS THE STRING INTO TEXT ELEMENTS
875 if(std::getline(fseed
,str
))
881 text_info_elementst
*newel
;
882 long end
=str
.length();
886 if(isspace(str
[end
-1]))end
--;
892 for(curpos
=0;curpos
<end
;curpos
++)
894 //HANDLE TOKEN OR ENDING
895 //TWO FILE TOKENS IN A ROW MEANS LONG
897 if(str
[curpos
]==file_token
|| curpos
==end
-1)
899 if(str
[curpos
]!=file_token
)nextstr
+=str
[curpos
];
901 //HAVE SOMETHING == SAVE IT
906 newel
=new text_info_element_longst(atoi(nextstr
.c_str()));
907 text
.element
.push_back(newel
);
912 newel
=new text_info_element_stringst(nextstr
);
913 text
.element
.push_back(newel
);
924 //JUST ADD IN ANYTHING ELSE
927 nextstr
+=str
[curpos
];
935 void curses_text_boxst::add_paragraph(const string
&src
,int32_t para_width
)
939 add_paragraph(sp
,para_width
);
942 void curses_text_boxst::add_paragraph(stringvectst
&src
,int32_t para_width
)
944 bool skip_leading_spaces
=false;
946 //ADD EACH OF THE STRINGS ON IN TURN
950 for(s
=0;s
<src
.str
.size();s
++)
952 //GRAB EACH WORD, AND SEE IF IT FITS, IF NOT START A NEW LINE
953 for(pos
=0;pos
<src
.str
[s
]->dat
.size();pos
++)
955 if(skip_leading_spaces
)
957 if(src
.str
[s
]->dat
[pos
]==' ')continue;
958 else skip_leading_spaces
=false;
962 curstr
+=src
.str
[s
]->dat
[pos
];
964 //IF TOO LONG, CUT BACK TO FIRST SPACE
965 if(curstr
.length()>para_width
)
974 }while(src
.str
[s
]->dat
[pos
]!=' '&&pos
>0);
976 //IF WENT ALL THE WAY BACK, INTRODUCE A SPACE
977 if(minus
==curstr
.size())
979 src
.str
[s
]->dat
.insert(opos
-1," ");
983 curstr
.resize(curstr
.size()-minus
);
984 text
.add_string(curstr
);
985 skip_leading_spaces
=true;
993 if(!curstr
.empty())text
.add_string(curstr
);